diff --git a/change_log.txt b/change_log.txt index c4f5c6d0d2..4e242a3063 100644 --- a/change_log.txt +++ b/change_log.txt @@ -5,6 +5,22 @@ Please add newer entries at the top, list the date and your name with email address. +2007-Dec-18 UPDATE Jean-Pierre Charras +================================================================================ ++pcbnew: + rework of drill filles creation (excellon and reports) + needed to have a clean implantation of buried vias and mainly microvia + which involve a more complex drill files generation + This is better to continue work on zones because : + hight density boards = use of BGA = microvias + good zones handling + When a board has buried or blind vias (microvia are blind vias), + pcbnew creates a drill file per layer pair. for a 4 layer board: + drill file for layer1 to layer 2 + drill file for layer2 to layer 3 + drill file for layer3 to layer 4 + + + 2008-Jan-18 UPDATE Dick Hollenbeck ================================================================================ how-to-build-kicad.txt: added the Boost C++ Libraries installation info diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp index fe7e1d6693..0f6ab00317 100644 --- a/pcbnew/class_track.cpp +++ b/pcbnew/class_track.cpp @@ -323,7 +323,9 @@ void SEGVIA::SetLayerPair( int top_layer, int bottom_layer ) void SEGVIA::ReturnLayerPair( int* top_layer, int* bottom_layer ) const /*********************************************************************/ -/* Return the 2 layers used by the via (the via actually uses +/** + * Function ReturnLayerPair + * Return the 2 layers used by the via (the via actually uses * all layers between these 2 layers) * @param top_layer = pointer to the first layer (can be null) * @param bottom_layer = pointer to the last layer (can be null) diff --git a/pcbnew/dialog_gendrill.h b/pcbnew/dialog_gendrill.h index 39316249f0..e49f668a43 100644 --- a/pcbnew/dialog_gendrill.h +++ b/pcbnew/dialog_gendrill.h @@ -149,14 +149,13 @@ private: void InitDisplayParams(void); void SetParams(void); void GenDrillFiles( wxCommandEvent& event ); - void GenDrillMap( std::vector & buffer, int format ); + void GenDrillMap( const wxString aFileName, std::vector & aHoleListBuffer, std::vector & aToolListBuffer, int format ); void UpdatePrecisionOptions( wxCommandEvent& event ); void UpdateConfig(); - int Plot_Drill_PcbMap( std::vector & buffer, int format ); - void GenDrillReport( std::vector & buffer ); - int Gen_Liste_Forets( std::vector & buffer, bool print_header ); - int Create_Drill_File_EXCELLON( std::vector & buffer ); - void Init_Drill(); + void Write_Excellon_Header( FILE * aFile); + void GenDrillReport( const wxString aFileName, std::vector & buffer ); + int Create_Drill_File_EXCELLON( std::vector & aHoleListBuffer, + std::vector & aToolListBuffer ); int Gen_Liste_Tools( std::vector & buffer, bool print_header ); }; diff --git a/pcbnew/dialog_track_options.cpp b/pcbnew/dialog_track_options.cpp index 5bcef3ba00..b2e57cd196 100644 --- a/pcbnew/dialog_track_options.cpp +++ b/pcbnew/dialog_track_options.cpp @@ -297,12 +297,6 @@ void WinEDA_PcbTracksDialog::AcceptPcbOptions(wxCommandEvent& event) g_DesignSettings.m_CurrentViaType = VIA_THROUGH; if ( m_OptViaType->GetSelection() > 0 ) g_DesignSettings.m_CurrentViaType = VIA_BLIND_BURIED; - if ( g_DesignSettings.m_CurrentViaType != VIA_THROUGH ) - { - if( ! IsOK(this, - _("You have selected VIA Blind and Buried\nWARNING: this feature is EXPERIMENTAL!!! Accept ?") ) ) - g_DesignSettings.m_CurrentViaType = VIA_THROUGH; - } g_DesignSettings.m_CurrentViaSize = ReturnValueFromTextCtrl(*m_OptViaSize, m_Parent->m_InternalUnits); diff --git a/pcbnew/gen_drill_report_files.cpp b/pcbnew/gen_drill_report_files.cpp new file mode 100644 index 0000000000..4989f2a7a6 --- /dev/null +++ b/pcbnew/gen_drill_report_files.cpp @@ -0,0 +1,676 @@ +/*************************************************************************/ +/* Functions to create drill data used to create aFiles and report aFiles */ +/*************************************************************************/ + +#include "fctsys.h" + +using namespace std; + +#include + +#include "common.h" +#include "plot_common.h" +#include "pcbnew.h" +#include "pcbplot.h" +#include "macros.h" +#include "gendrill.h" + +static void PlotDrillSymbol( const wxPoint& position, int diametre, int aShapeId, int format ); +static void PlotOvalDrillSymbol( const wxPoint& position, + const wxSize& size, + int orient, + int format ); + + +/**********************************************************************************/ +void GenDrillMapFile( BOARD* aPcb, FILE* aFile, const wxString& aFullFileName, wxSize aSheetSize, + std::vector aHoleListBuffer, + std::vector aToolListBuffer, + bool aUnit_Drill_is_Inch, int format ) +/**********************************************************************************/ + +/* Genere le plan de percage (Drill map) format HPGL ou POSTSCRIPT + */ +{ + unsigned ii; + int x, y; + int plotX, plotY, TextWidth; + int intervalle = 0, CharSize = 0; + EDA_BaseStruct* PtStruct; + int old_g_PlotOrient = g_PlotOrient; + char line[1024]; + int dX, dY; + wxPoint BoardCentre; + int PlotMarge_in_mils = 400; // Margin in 1/1000 inch + int marge = PlotMarge_in_mils * U_PCB; + wxSize SheetSize; + float fTextScale = 1.0; + double scale_x = 1.0, scale_y = 1.0; + Ki_PageDescr* SheetPS = NULL; + wxString msg; + + + setlocale( LC_NUMERIC, "C" ); // Use the standard notation for float numbers + g_PlotOrient = 0; + /* calcul des dimensions et centre du PCB */ + aPcb->ComputeBoundaryBox(); + + dX = aPcb->m_BoundaryBox.GetWidth(); + dY = aPcb->m_BoundaryBox.GetHeight(); + BoardCentre = aPcb->m_BoundaryBox.Centre(); + + // Calcul de l'echelle du dessin du PCB, + // Echelle 1 en HPGL, dessin sur feuille A4 en PS, + texte description des symboles + switch( format ) + { + case PLOT_FORMAT_HPGL: /* Calcul des echelles de conversion format HPGL */ + Scale_X = Scale_Y = 1.0; + scale_x = Scale_X * SCALE_HPGL; + scale_y = Scale_Y * SCALE_HPGL; + fTextScale = SCALE_HPGL; + SheetSize = aSheetSize; + SheetSize.x *= U_PCB; + SheetSize.y *= U_PCB; + g_PlotOffset.x = 0; + g_PlotOffset.y = (int) (SheetSize.y * scale_y); + break; + + case PLOT_FORMAT_POST: + { + // calcul en unites internes des dimensions de la feuille ( connues en 1/1000 pouce ) + SheetPS = &g_Sheet_A4; + SheetSize.x = SheetPS->m_Size.x * U_PCB; + SheetSize.y = SheetPS->m_Size.y * U_PCB; + float Xscale = (float) ( SheetSize.x - (marge * 2) ) / dX; + float Yscale = (float) ( SheetSize.y * 0.6 - (marge * 2) ) / dY; + + scale_x = scale_y = MIN( Xscale, Yscale ); + + g_PlotOffset.x = -(SheetSize.x / 2) + + (int) (BoardCentre.x * scale_x) + marge; + g_PlotOffset.y = SheetSize.y / 2 + + (int) (BoardCentre.y * scale_y) - marge; + g_PlotOffset.y += SheetSize.y / 8; /* decalage pour legende */ + break; + } + + default: + break; + } + + switch( format ) + { + case PLOT_FORMAT_HPGL: + InitPlotParametresHPGL( g_PlotOffset, scale_x, scale_y ); + PrintHeaderHPGL( aFile, g_HPGL_Pen_Speed, g_HPGL_Pen_Num ); + break; + + case PLOT_FORMAT_POST: + { + int BBox[4]; + BBox[0] = BBox[1] = PlotMarge_in_mils; + BBox[2] = SheetPS->m_Size.x - PlotMarge_in_mils; + BBox[3] = SheetPS->m_Size.y - PlotMarge_in_mils; + InitPlotParametresPS( g_PlotOffset, + SheetPS, + (double) 1.0 / PCB_INTERNAL_UNIT, + (double) 1.0 / PCB_INTERNAL_UNIT ); + SetDefaultLineWidthPS( 10 ); // Set line with to 10/1000 inch + PrintHeaderPS( aFile, wxT( "PCBNEW-PS" ), aFullFileName, 1, BBox, wxLANDSCAPE ); + InitPlotParametresPS( g_PlotOffset, SheetPS, scale_x, scale_y ); + } + break; + + default: + break; + } + + /* Draw items on edge layer */ + PtStruct = aPcb->m_Drawings; + for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext ) + { + switch( PtStruct->Type() ) + { + case TYPEDRAWSEGMENT: + PlotDrawSegment( (DRAWSEGMENT*) PtStruct, format, EDGE_LAYER ); + break; + + case TYPETEXTE: + PlotTextePcb( (TEXTE_PCB*) PtStruct, format, EDGE_LAYER ); + break; + + case TYPECOTATION: + PlotCotation( (COTATION*) PtStruct, format, EDGE_LAYER ); + break; + + case TYPEMIRE: + PlotMirePcb( (MIREPCB*) PtStruct, format, EDGE_LAYER ); + break; + + case TYPEMARKER: // do not draw + break; + + default: + DisplayError( NULL, wxT( "WinEDA_DrillFrame::GenDrillMap() : Unexpected Draw Type" ) ); + break; + } + } + + TextWidth = 50; // Set Drill Symbols width in 1/10000 mils + + if( format == PLOT_FORMAT_POST ) + { + sprintf( line, "%d setlinewidth\n", TextWidth ); + fputs( line, aFile ); + } + + Gen_Drill_PcbMap( aPcb, aFile, aHoleListBuffer, aToolListBuffer, format ); + + /* Impression de la liste des symboles utilises */ + CharSize = 800; /* text size in 1/10000 mils */ + float CharScale = 1.0 / scale_x; /* real scale will be CharScale * scale_x, + * because the global plot scale is scale_x */ + TextWidth = (int) (50 * CharScale); // Set text width + intervalle = (int) (CharSize * CharScale) + TextWidth; + + switch( format ) + { + case PLOT_FORMAT_HPGL: + { + /* generation des dim: commande SI x,y; x et y = dim en cm */ + char csize[256]; + sprintf( csize, "%2.3f", (float) CharSize * CharScale * 0.000254 ); + sprintf( line, "SI %s, %s;\n", csize, csize ); + break; + } + + case PLOT_FORMAT_POST: + /* Reglage de l'epaisseur de traits des textes */ + sprintf( line, "%d setlinewidth\n", TextWidth ); + break; + + default: + *line = 0; + break; + } + + fputs( line, aFile ); + + switch( format ) + { + default: + case PLOT_FORMAT_POST: + g_PlotOffset.x = 0; + g_PlotOffset.y = 0; + InitPlotParametresPS( g_PlotOffset, SheetPS, scale_x, scale_x ); + break; + + case PLOT_FORMAT_HPGL: + InitPlotParametresHPGL( g_PlotOffset, scale_x, scale_x ); + break; + } + + /* Trace des informations */ + + /* Trace de "Infos" */ + plotX = marge + 1000; + plotY = CharSize + 1000; + x = plotX; y = plotY; + x = +g_PlotOffset.x + (int) (x * fTextScale); + y = g_PlotOffset.y - (int) (y * fTextScale); + + plotY += (int) ( intervalle * 1.2) + 200; + + switch( format ) + { + case PLOT_FORMAT_HPGL: + sprintf( line, "PU %d, %d; LBInfos\03;\n", + x + (int) (intervalle * CharScale * fTextScale), + y - (int) (CharSize / 2 * CharScale * fTextScale) ); + fputs( line, aFile ); + break; + + case PLOT_FORMAT_POST: + wxString Text = wxT( "Infos" ); + Plot_1_texte( format, Text, 0, TextWidth, + x, y, + (int) (CharSize * CharScale), (int) (CharSize * CharScale), + FALSE ); + break; + } + + + for( ii = 0; ii < aToolListBuffer.size(); ii++ ) + { + int plot_diam; + if( aToolListBuffer[ii].m_TotalCount == 0 ) + continue; + + plot_diam = (int) (aToolListBuffer[ii].m_Diameter); + x = plotX; y = plotY; + x = -g_PlotOffset.x + (int) (x * fTextScale); + y = g_PlotOffset.y - (int) (y * fTextScale); + PlotDrillSymbol( wxPoint( x, y ), plot_diam, ii, format ); + + intervalle = (int) (CharSize * CharScale) + TextWidth; + intervalle = (int) ( intervalle * 1.2); + + if( intervalle < (plot_diam + 200 + TextWidth) ) + intervalle = plot_diam + 200 + TextWidth; + + int rayon = plot_diam / 2; + x = plotX + rayon + (int) (CharSize * CharScale); y = plotY; + x = -g_PlotOffset.x + (int) (x * fTextScale); + y = g_PlotOffset.y - (int) (y * fTextScale); + + /* Trace de la legende associee */ + switch( format ) + { + case PLOT_FORMAT_HPGL: + + // List the diameter of each drill in the selected Drill Unit, + // and then its diameter in the other Drill Unit. + if( aUnit_Drill_is_Inch ) + sprintf( line, "PU %d, %d; LB%2.3f\" / %2.2fmm ", + x + (int) (intervalle * CharScale * fTextScale), + y - (int) (CharSize / 2 * CharScale * fTextScale), + float (aToolListBuffer[ii].m_Diameter) * 0.0001, + float (aToolListBuffer[ii].m_Diameter) * 0.00254 ); + else + sprintf( line, "PU %d, %d; LB%2.2fmm / %2.3f\" ", + x + (int) (intervalle * CharScale * fTextScale), + y - (int) (CharSize / 2 * CharScale * fTextScale), + float (aToolListBuffer[ii].m_Diameter) * 0.00254, + float (aToolListBuffer[ii].m_Diameter) * 0.0001 ); + fputs( line, aFile ); + + // Now list how many holes and ovals are associated with each drill. + if( ( aToolListBuffer[ii].m_TotalCount == 1 ) && + ( aToolListBuffer[ii].m_OvalCount == 0 ) ) + sprintf( line, "(1 hole)\n" ); + else if( aToolListBuffer[ii].m_TotalCount == 1 ) // && ( buffer[ii]m_OvalCount == 1 ) + sprintf( line, "(1 hole) (with 1 oblong)\n" ); + else if( aToolListBuffer[ii].m_OvalCount == 0 ) + sprintf( line, "(%d holes)\n", + aToolListBuffer[ii].m_TotalCount ); + else if( aToolListBuffer[ii].m_OvalCount == 1 ) + sprintf( line, "(%d holes) (with 1 oblong)\n", + aToolListBuffer[ii].m_TotalCount ); + else // if ( aToolListBuffer[ii]m_OvalCount > 1 ) + sprintf( line, "(%d holes) (with %d oblongs)\n", + aToolListBuffer[ii].m_TotalCount, + aToolListBuffer[ii].m_OvalCount ); + fputs( line, aFile ); + fputs( "\03;\n", aFile ); + break; + + case PLOT_FORMAT_POST: + + // List the diameter of each drill in the selected Drill Unit, + // and then its diameter in the other Drill Unit. + if( aUnit_Drill_is_Inch ) + sprintf( line, "%2.3f\" / %2.2fmm ", + float (aToolListBuffer[ii].m_Diameter) * 0.0001, + float (aToolListBuffer[ii].m_Diameter) * 0.00254 ); + else + sprintf( line, "%2.2fmm / %2.3f\" ", + float (aToolListBuffer[ii].m_Diameter) * 0.00254, + float (aToolListBuffer[ii].m_Diameter) * 0.0001 ); + msg = CONV_FROM_UTF8( line ); + + // Now list how many holes and ovals are associated with each drill. + if( ( aToolListBuffer[ii].m_TotalCount == 1 ) && + ( aToolListBuffer[ii].m_OvalCount == 0 ) ) + sprintf( line, "(1 hole)" ); + else if( aToolListBuffer[ii].m_TotalCount == 1 ) // && ( aToolListBuffer[ii]m_OvalCount == 1 ) + sprintf( line, "(1 hole) (with 1 oblong)" ); + else if( aToolListBuffer[ii].m_OvalCount == 0 ) + sprintf( line, "(%d holes)", + aToolListBuffer[ii].m_TotalCount ); + else if( aToolListBuffer[ii].m_OvalCount == 1 ) + sprintf( line, "(%d holes) (with 1 oblong)", + aToolListBuffer[ii].m_TotalCount ); + else // if ( aToolListBuffer[ii]m_OvalCount > 1 ) + sprintf( line, "(%d holes) (with %d oblongs)", + aToolListBuffer[ii].m_TotalCount, + aToolListBuffer[ii].m_OvalCount ); + msg += CONV_FROM_UTF8( line ); + Plot_1_texte( format, msg, 0, TextWidth, + x, y, + (int) (CharSize * CharScale), + (int) (CharSize * CharScale), + FALSE ); + break; + } + + plotY += intervalle; + } + + switch( format ) + { + case PLOT_FORMAT_HPGL: + CloseFileHPGL( aFile ); + break; + + case PLOT_FORMAT_POST: + CloseFilePS( aFile ); + break; + } + + setlocale( LC_NUMERIC, "" ); // Revert to local notation for float numbers + + g_PlotOrient = old_g_PlotOrient; +} + + +/****************************************************************************************/ +void Gen_Drill_PcbMap( BOARD* aPcb, FILE* aFile, + std::vector& aHoleListBuffer, + std::vector& aToolListBuffer, + int format ) +/****************************************************************************************/ + +/** Creates the drill map aFile in HPGL or POSTSCRIPT format + * @param aPcb BOARD + * @param aFile = output aFile + * @param aHoleListBuffer = std::vector list of holes descriptors + * @param aToolListBuffer = std::vector drill list buffer + * @param format = ouput format (hpgl / ps) + */ +{ + wxPoint pos; + + /* create the drill list */ + if( aToolListBuffer.size() > 13 ) + { + DisplayInfo( NULL, + _( + " Drill map: Too many diameter values to draw to draw one symbol per drill value (max 13)\nPlot uses circle shape for some drill values" ), + 10 ); + } + + // Plot the drill map: + for( unsigned ii = 0; ii < aHoleListBuffer.size(); ii++ ) + { + pos.x = aHoleListBuffer[ii].m_Hole_Pos_X; + pos.y = aHoleListBuffer[ii].m_Hole_Pos_Y; + + if( aHoleListBuffer[ii].m_Hole_Shape == 0 ) + { + PlotDrillSymbol( pos, aHoleListBuffer[ii].m_Hole_Diameter, + aHoleListBuffer[ii].m_Tool_Reference - 1, + format ); + } + else + { + wxSize oblong_size; + oblong_size.x = aHoleListBuffer[ii].m_Hole_SizeX; + oblong_size.y = aHoleListBuffer[ii].m_Hole_SizeY; + PlotOvalDrillSymbol( pos, oblong_size, aHoleListBuffer[ii].m_Hole_Orient, format ); + } + } +} + + +/************************************************************************************/ +void PlotDrillSymbol( const wxPoint& position, int diametre, int aShapeId, int format ) +/************************************************************************************/ + +/* Trace un motif de numero de forme aShapeId, aux coord x0, y0. + * x0, y0 = coordonnees tables + * diametre = diametre (coord table) du trou + * aShapeId = index ( permet de generer des formes caract ) + */ +{ + int rayon = diametre / 2; + + void (*FctPlume)( wxPoint pos, int state ); + int x0, y0; + + x0 = position.x; y0 = position.y; + FctPlume = Move_Plume_HPGL; + if( format == PLOT_FORMAT_POST ) + FctPlume = LineTo_PS; + + switch( aShapeId ) + { + case 0: /* vias : forme en X */ + FctPlume( wxPoint( x0 - rayon, y0 - rayon ), 'U' ); + FctPlume( wxPoint( x0 + rayon, y0 + rayon ), 'D' ); + FctPlume( wxPoint( x0 + rayon, y0 - rayon ), 'U' ); + FctPlume( wxPoint( x0 - rayon, y0 + rayon ), 'D' ); + break; + + case 1: /* Cercle */ + if( format == PLOT_FORMAT_HPGL ) + trace_1_pastille_RONDE_HPGL( wxPoint( x0, y0 ), diametre, FILAIRE ); + if( format == PLOT_FORMAT_POST ) + trace_1_pastille_RONDE_POST( wxPoint( x0, y0 ), diametre, FILAIRE ); + break; + + case 2: /* forme en + */ + FctPlume( wxPoint( x0, y0 - rayon ), 'U' ); + FctPlume( wxPoint( x0, y0 + rayon ), 'D' ); + FctPlume( wxPoint( x0 + rayon, y0 ), 'U' ); + FctPlume( wxPoint( x0 - rayon, y0 ), 'D' ); + break; + + case 3: /* forme en X cercle */ + FctPlume( wxPoint( x0 - rayon, y0 - rayon ), 'U' ); + FctPlume( wxPoint( x0 + rayon, y0 + rayon ), 'D' ); + FctPlume( wxPoint( x0 + rayon, y0 - rayon ), 'U' ); + FctPlume( wxPoint( x0 - rayon, y0 + rayon ), 'D' ); + if( format == PLOT_FORMAT_HPGL ) + trace_1_pastille_RONDE_HPGL( wxPoint( x0, y0 ), diametre, FILAIRE ); + if( format == PLOT_FORMAT_POST ) + trace_1_pastille_RONDE_POST( wxPoint( x0, y0 ), diametre, FILAIRE ); + break; + + case 4: /* forme en cercle barre de - */ + FctPlume( wxPoint( x0 - rayon, y0 ), 'U' ); + FctPlume( wxPoint( x0 + rayon, y0 ), 'D' ); + if( format == PLOT_FORMAT_HPGL ) + trace_1_pastille_RONDE_HPGL( wxPoint( x0, y0 ), diametre, FILAIRE ); + if( format == PLOT_FORMAT_POST ) + trace_1_pastille_RONDE_POST( wxPoint( x0, y0 ), diametre, FILAIRE ); + break; + + case 5: /* forme en cercle barre de | */ + FctPlume( wxPoint( x0, y0 - rayon ), 'U' ); + FctPlume( wxPoint( x0, y0 + rayon ), 'D' ); + if( format == PLOT_FORMAT_HPGL ) + trace_1_pastille_RONDE_HPGL( wxPoint( x0, y0 ), diametre, FILAIRE ); + if( format == PLOT_FORMAT_POST ) + trace_1_pastille_RONDE_POST( wxPoint( x0, y0 ), diametre, FILAIRE ); + break; + + case 6: /* forme en carre */ + if( format == PLOT_FORMAT_HPGL ) + trace_1_pad_TRAPEZE_HPGL( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, + 0 ), 0, + FILAIRE ); + if( format == PLOT_FORMAT_POST ) + trace_1_pad_TRAPEZE_POST( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, + 0 ), 0, + FILAIRE ); + break; + + case 7: /* forme en losange */ + if( format == PLOT_FORMAT_HPGL ) + trace_1_pad_TRAPEZE_HPGL( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, + 0 ), 450, + FILAIRE ); + if( format == PLOT_FORMAT_POST ) + trace_1_pad_TRAPEZE_POST( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, + 0 ), 450, + FILAIRE ); + break; + + case 8: /* forme en carre barre par un X*/ + FctPlume( wxPoint( x0 - rayon, y0 - rayon ), 'U' ); + FctPlume( wxPoint( x0 + rayon, y0 + rayon ), 'D' ); + FctPlume( wxPoint( x0 + rayon, y0 - rayon ), 'U' ); + FctPlume( wxPoint( x0 - rayon, y0 + rayon ), 'D' ); + if( format == PLOT_FORMAT_HPGL ) + trace_1_pad_TRAPEZE_HPGL( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, + 0 ), 0, + FILAIRE ); + if( format == PLOT_FORMAT_POST ) + trace_1_pad_TRAPEZE_POST( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, + 0 ), 0, + FILAIRE ); + break; + + case 9: /* forme en losange barre par un +*/ + FctPlume( wxPoint( x0, y0 - rayon ), 'U' ); + FctPlume( wxPoint( x0, y0 + rayon ), 'D' ); + FctPlume( wxPoint( x0 + rayon, y0 ), 'U' ); + FctPlume( wxPoint( x0 - rayon, y0 ), 'D' ); + if( format == PLOT_FORMAT_HPGL ) + trace_1_pad_TRAPEZE_HPGL( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, + 0 ), 450, + FILAIRE ); + if( format == PLOT_FORMAT_POST ) + trace_1_pad_TRAPEZE_POST( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, + 0 ), 450, + FILAIRE ); + break; + + case 10: /* forme en carre barre par un '/' */ + FctPlume( wxPoint( x0 - rayon, y0 - rayon ), 'U' ); + FctPlume( wxPoint( x0 + rayon, y0 + rayon ), 'D' ); + if( format == PLOT_FORMAT_HPGL ) + trace_1_pad_TRAPEZE_HPGL( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, + 0 ), 0, + FILAIRE ); + if( format == PLOT_FORMAT_POST ) + trace_1_pad_TRAPEZE_POST( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, + 0 ), 0, + FILAIRE ); + break; + + case 11: /* forme en losange barre par un |*/ + FctPlume( wxPoint( x0, y0 - rayon ), 'U' ); + FctPlume( wxPoint( x0, y0 + rayon ), 'D' ); + if( format == PLOT_FORMAT_HPGL ) + trace_1_pad_TRAPEZE_HPGL( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, + 0 ), 450, + FILAIRE ); + if( format == PLOT_FORMAT_POST ) + trace_1_pad_TRAPEZE_POST( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, + 0 ), 450, + FILAIRE ); + break; + + case 12: /* forme en losange barre par un -*/ + FctPlume( wxPoint( x0 - rayon, y0 ), 'U' ); + FctPlume( wxPoint( x0 + rayon, y0 ), 'D' ); + if( format == PLOT_FORMAT_HPGL ) + trace_1_pad_TRAPEZE_HPGL( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, + 0 ), 450, + FILAIRE ); + if( format == PLOT_FORMAT_POST ) + trace_1_pad_TRAPEZE_POST( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, + 0 ), 450, + FILAIRE ); + break; + + default: + if( format == PLOT_FORMAT_HPGL ) + trace_1_pastille_RONDE_HPGL( wxPoint( x0, y0 ), diametre, FILAIRE ); + if( format == PLOT_FORMAT_POST ) + trace_1_pastille_RONDE_POST( wxPoint( x0, y0 ), diametre, FILAIRE ); + break; + } + + if( format == PLOT_FORMAT_HPGL ) + Plume_HPGL( 'U' ); +} + + +/*********************************************************************************************/ +void PlotOvalDrillSymbol( const wxPoint& position, const wxSize& size, int orient, int format ) +/*********************************************************************************************/ + +/* Draws an oblong hole. + * because functions to draw oblong shapes exist to draw oblong pads, Use they. + */ +{ + switch( format ) + { + case PLOT_FORMAT_HPGL: + trace_1_pastille_OVALE_HPGL( position, size, orient, FILAIRE ); + break; + + case PLOT_FORMAT_POST: + trace_1_pastille_OVALE_POST( position, size, orient, FILAIRE ); + break; + } +} + + +/**************************************************************************************************/ +void GenDrillReportFile( FILE* aFile, const wxString& aBoardFilename, + std::vector& aToolListBuffer, bool aUnit_Drill_is_Inch ) +/*************************************************************************************************/ + +/* + * Create a list of drill values and drill count + */ +{ + unsigned TotalHoleCount; + char line[1024]; + + fprintf( aFile, "Drill report for %s\n", CONV_TO_UTF8( aBoardFilename ) ); + fprintf( aFile, "Created on %s\n", DateAndTime( line ) ); + + // List which Drill Unit option had been selected for the associated drill aFile. + if( aUnit_Drill_is_Inch ) + fputs( "Selected Drill Unit: Imperial (\")\n\n", aFile ); + else + fputs( "Selected Drill Unit: Metric (mm)\n\n", aFile ); + + TotalHoleCount = 0; + + for( unsigned ii = 0; ii < aToolListBuffer.size(); ii++ ) + { + // List the tool number assigned to each drill, + // then its diameter in the selected Drill Unit, + // and then its diameter in the other Drill Unit. + if( aUnit_Drill_is_Inch ) + sprintf( line, "T%d %2.3f\" %2.2fmm ", + ii + 1, + float (aToolListBuffer[ii].m_Diameter) * 0.0001, + float (aToolListBuffer[ii].m_Diameter) * 0.00254 ); + else + sprintf( line, "T%d %2.2fmm %2.3f\" ", + ii + 1, + float (aToolListBuffer[ii].m_Diameter) * 0.00254, + float (aToolListBuffer[ii].m_Diameter) * 0.0001 ); + fputs( line, aFile ); + + // Now list how many holes and ovals are associated with each drill. + if( ( aToolListBuffer[ii].m_TotalCount == 1 ) && ( aToolListBuffer[ii].m_OvalCount == 0 ) ) + sprintf( line, "(1 hole)\n" ); + else if( aToolListBuffer[ii].m_TotalCount == 1 ) + sprintf( line, "(1 hole) (with 1 oblong)\n" ); + else if( aToolListBuffer[ii].m_OvalCount == 0 ) + sprintf( line, "(%d holes)\n", + aToolListBuffer[ii].m_TotalCount ); + else if( aToolListBuffer[ii].m_OvalCount == 1 ) + sprintf( line, "(%d holes) (with 1 oblong)\n", + aToolListBuffer[ii].m_TotalCount ); + else // if ( buffer[ii]m_OvalCount > 1 ) + sprintf( line, "(%d holes) (with %d oblongs)\n", + aToolListBuffer[ii].m_TotalCount, + aToolListBuffer[ii].m_OvalCount ); + fputs( line, aFile ); + + TotalHoleCount += aToolListBuffer[ii].m_TotalCount; + } + + sprintf( line, "\ntotal holes count %d\n", TotalHoleCount ); + fputs( line, aFile ); + + fclose( aFile ); +} diff --git a/pcbnew/gen_holes_and_tools_lists_for_drill.cpp b/pcbnew/gen_holes_and_tools_lists_for_drill.cpp new file mode 100644 index 0000000000..e324afed02 --- /dev/null +++ b/pcbnew/gen_holes_and_tools_lists_for_drill.cpp @@ -0,0 +1,132 @@ +/*************************************************************************/ +/* Functions to create drill data used to create files and report files */ +/*************************************************************************/ + +#include "fctsys.h" + +using namespace std; + +#include + +#include "common.h" +#include "plot_common.h" +#include "pcbnew.h" +#include "pcbplot.h" +#include "macros.h" +#include "gendrill.h" + + +/* Local Functions */ +/* Compare function used for sorting holes by increasing diameter value */ +static bool CmpHoleDiameterValue( const HOLE_INFO& a, const HOLE_INFO& b ) +{ + return a.m_Hole_Diameter < b.m_Hole_Diameter; +} + + +/** + * Function BuildHolesList + * Create the list of holes and tools for a given board + * The list is sorted by incraesin drill values + * Only holes from aFirstLayer to aLastLayer copper layers are listed (for vias, because pad holes are always through holes) + * @param Pcb : the given board + * @param aHoleListBuffer : the std::vector to fill with pcb holes info + * @param aToolListBuffer : the std::vector to fill with tools to use + * @param aFirstLayer = first layer to consider + * @param aLastLayer = last layer to consider + */ +void Build_Holes_List( BOARD* aPcb, + std::vector& aHoleListBuffer, + std::vector& aToolListBuffer, + int aFirstLayer, int aLastLayer ) +{ + HOLE_INFO new_hole; + int hole_value; + + aHoleListBuffer.clear(); + aToolListBuffer.clear(); + + if( aFirstLayer > aLastLayer ) + EXCHG( aFirstLayer, aLastLayer ); + + /* build hole list for vias */ + TRACK* track = aPcb->m_Track; + for( ; track != NULL; track = track->Next() ) + { + if( track->Type() != TYPEVIA ) + continue; + SEGVIA* via = (SEGVIA*) track; + hole_value = via->GetDrillValue(); + if( hole_value == 0 ) + continue; + new_hole.m_Tool_Reference = -1; // Flag value for Not initialized + new_hole.m_Hole_Orient = 0; + new_hole.m_Hole_Diameter = hole_value; + new_hole.m_Hole_SizeX = new_hole.m_Hole_SizeY = new_hole.m_Hole_Diameter; + new_hole.m_Hole_Shape = 0; // hole shape: round + new_hole.m_Hole_Pos_X = via->m_Start.x; + new_hole.m_Hole_Pos_Y = via->m_Start.y; // hole position + via->ReturnLayerPair( &new_hole.m_Hole_Top_Layer, &new_hole.m_Hole_Bottom_Layer ); + // ReturnLayerPair return params with m_Hole_Bottom_Layer < m_Hole_Top_Layer + if( new_hole.m_Hole_Bottom_Layer > aFirstLayer ) + continue; + if( new_hole.m_Hole_Top_Layer < aLastLayer ) + continue; + aHoleListBuffer.push_back( new_hole ); + } + + /* build hole list for pads */ + MODULE* Module = aPcb->m_Modules; + for( ; Module != NULL; Module = Module->Next() ) + { + /* Read and analyse pads */ + D_PAD* pad = Module->m_Pads; + for( ; pad != NULL; pad = pad->Next() ) + { + if( pad->m_Drill.x == 0 ) + continue; + new_hole.m_Tool_Reference = -1; // Flag is: Not initialized + new_hole.m_Hole_Orient = pad->m_Orient; + new_hole.m_Hole_Shape = 0; // hole shape: round + new_hole.m_Hole_Diameter = min( pad->m_Drill.x, pad->m_Drill.x ); + new_hole.m_Hole_SizeX = new_hole.m_Hole_SizeY = new_hole.m_Hole_Diameter; + if( pad->m_DrillShape != PAD_CIRCLE ) + new_hole.m_Hole_Shape = 1; // oval flag set + new_hole.m_Hole_SizeX = pad->m_Drill.x; + new_hole.m_Hole_SizeY = pad->m_Drill.y; + new_hole.m_Hole_Pos_X = pad->m_Pos.x; + new_hole.m_Hole_Pos_Y = pad->m_Pos.y; // hole position + new_hole.m_Hole_Bottom_Layer = COPPER_LAYER_N; + new_hole.m_Hole_Top_Layer = LAYER_CMP_N; // pad holes are through holes + aHoleListBuffer.push_back( new_hole ); + } + } + + // Sort holes per increasing diameter value + sort( aHoleListBuffer.begin(), aHoleListBuffer.end(), CmpHoleDiameterValue ); + + // build the tool list + int LastHole = -1; /* Set to not initialised + * (this is a value not used for aHoleListBuffer[ii].m_Hole_Diameter) */ + DRILL_TOOL new_tool( 0 ); + unsigned jj; + for( unsigned ii = 0; ii < aHoleListBuffer.size(); ii++ ) + { + if( aHoleListBuffer[ii].m_Hole_Diameter != LastHole ) + { + new_tool.m_Diameter = ( aHoleListBuffer[ii].m_Hole_Diameter ); + aToolListBuffer.push_back( new_tool ); + LastHole = new_tool.m_Diameter; + } + + jj = aToolListBuffer.size(); + if( jj == 0 ) + continue; // Should not occurs + + aHoleListBuffer[ii].m_Tool_Reference = jj; // Tool value Initialized (value >= 1) + + aToolListBuffer.back().m_TotalCount++; + if( aHoleListBuffer[ii].m_Hole_Shape ) + aToolListBuffer.back().m_OvalCount++; + } +} diff --git a/pcbnew/gendrill.cpp b/pcbnew/gendrill.cpp index 3a132a4587..4167eac661 100644 --- a/pcbnew/gendrill.cpp +++ b/pcbnew/gendrill.cpp @@ -15,6 +15,8 @@ using namespace std; #include "pcbplot.h" #include "macros.h" +#include "gendrill.h" + /* * Creates the drill files in EXCELLON format * Number format: @@ -30,52 +32,14 @@ using namespace std; * dialog_gendrill.cpp is the file (included in this file) which handles the Dialog box for drill file generation */ -class DRILL_TOOL -{ -public: - int m_Diameter; - int m_TotalCount; - int m_OvalCount; -public: - DRILL_TOOL( int diametre ) - { - m_TotalCount = 0; - m_OvalCount = 0; - m_Diameter = diametre; - } -}; - -/* drill precision format */ -class DrillPrecision -{ -public: - int m_lhs; - int m_rhs; - -public: - DrillPrecision( int l, int r ) { m_lhs = l; m_rhs = r; } -}; - -/* zeros format */ -enum zeros_fmt { - DECIMAL_FORMAT, - SUPPRESS_LEADING, - SUPPRESS_TRAILING, - KEEP_ZEROS -}; /* Local Function */ static void Gen_Line_EXCELLON( char* line, float x, float y ); -static void Write_End_Of_File_Drill(); -static void PlotDrillSymbol( const wxPoint& position, int diametre, int num_forme, int format ); -static void PlotOvalDrillSymbol( const wxPoint& position, - const wxSize& size, - int orient, - int format ); +static void Write_End_Of_File_Drill( FILE* aFile ); /* Local Variables : */ -static float conv_unit; /* coeff de conversion des unites drill / pcb */ -static int s_Unit_Drill_is_Inch = TRUE; /* INCH,LZ (2:4) */ +static float s_ConversionUnits; /* coeff de conversion des unites drill / pcb */ +static int s_Unit_Drill_is_Inch = TRUE; /* INCH,LZ (2:4) */ static int s_Zeros_Format = DECIMAL_FORMAT; static DrillPrecision s_Precision( 2, 4 ); @@ -85,6 +49,7 @@ static bool Minimal = false; static bool Mirror = true; static std::vector s_ToolListBuffer; +static std::vector s_HoleListBuffer; // Keywords for read and write config #define ZerosFormatKey wxT( "DrillZerosFormat" ) @@ -97,12 +62,6 @@ static std::vector s_ToolListBuffer; #include "dialog_gendrill.cpp" // Dialog box for drill file generation -/* Compare function used for sorting tools */ -static bool CmpDrillDiameterTool( const DRILL_TOOL& a, const DRILL_TOOL& b ) -{ - return a.m_Diameter < b.m_Diameter; -} - /**********************************************/ void WinEDA_DrillFrame::InitDisplayParams( void ) @@ -123,15 +82,15 @@ void WinEDA_DrillFrame::InitDisplayParams( void ) if( s_Zeros_Format==DECIMAL_FORMAT ) m_Choice_Precision->Enable( false ); - msg = ReturnStringFromValue( g_UnitMetric, - g_DesignSettings.m_ViaDrill, - m_Parent->m_InternalUnits ); + msg = ReturnStringFromValue( g_UnitMetric, + g_DesignSettings.m_ViaDrill, + m_Parent->m_InternalUnits ); msg += ReturnUnitSymbol( g_UnitMetric ); m_ViaDrillValue->SetLabel( msg ); - msg = ReturnStringFromValue( g_UnitMetric, - g_DesignSettings.m_MicroViaDrill, - m_Parent->m_InternalUnits ); + msg = ReturnStringFromValue( g_UnitMetric, + g_DesignSettings.m_MicroViaDrill, + m_Parent->m_InternalUnits ); msg += ReturnUnitSymbol( g_UnitMetric ); m_MicroViaDrillValue->SetLabel( msg ); @@ -296,79 +255,106 @@ void WinEDA_DrillFrame::GenDrillFiles( wxCommandEvent& event ) */ { wxString FullFileName, Mask( wxT( "*" ) ), Ext( wxT( ".drl" ) ); - int ii; wxString msg; + bool ExistsBuriedVias = false; // If true, driil files are created layer pair by layer pair + int layer1 = COPPER_LAYER_N; + int layer2 = LAYER_CMP_N; UpdateConfig(); /* set params and Save drill options */ m_Parent->MsgPanel->EraseMsgBox(); /* Set conversion scale depending on drill file units */ - conv_unit = 0.0001; /* unites = INCHES */ + s_ConversionUnits = 0.0001; /* unites = INCHES */ if( !s_Unit_Drill_is_Inch ) - conv_unit = 0.000254; /* unites = mm */ + s_ConversionUnits = 0.000254; /* unites = mm */ + if( m_MicroViasCount || m_BlindOrBuriedViasCount ) + ExistsBuriedVias = true; + + if( ExistsBuriedVias ) + layer2 = layer1 + 1;; /* Get the file name */ - FullFileName = m_Parent->m_CurrentScreen->m_FileName; - ChangeFileNameExt( FullFileName, Ext ); Mask += Ext; - - FullFileName = EDA_FileSelector( _( "Drill file" ), - wxEmptyString, /* Chemin par defaut */ - FullFileName, /* nom fichier par defaut */ - Ext, /* extension par defaut */ - Mask, /* Masque d'affichage */ - this, - wxFD_SAVE, - TRUE - ); - if( FullFileName != wxEmptyString ) + for( ; ; ) { - dest = wxFopen( FullFileName, wxT( "w" ) ); - if( dest == 0 ) + FullFileName = m_Parent->m_CurrentScreen->m_FileName; + wxString layer_extend; + layer_extend.Empty(); + if( ExistsBuriedVias ) { - msg = _( "Unable to create file " ) + FullFileName; - DisplayError( this, msg ); - EndModal( 0 ); - return; + if( layer1 == COPPER_LAYER_N ) + layer_extend << wxT( "-copper" ); + else + layer_extend << wxT( "-inner" ) << layer1; + if( layer2 == LAYER_CMP_N ) + layer_extend << wxT( "-cmp" ); + else + layer_extend << wxT( "-inner" ) << layer2; + } + layer_extend << Ext; + ChangeFileNameExt( FullFileName, layer_extend ); + + FullFileName = EDA_FileSelector( _( "Drill file" ), + wxEmptyString, /* Chemin par defaut */ + FullFileName, /* nom fichier par defaut */ + Ext, /* extension par defaut */ + Mask, /* Masque d'affichage */ + this, + wxFD_SAVE, + TRUE + ); + + Build_Holes_List( m_Parent->m_Pcb, s_HoleListBuffer, s_ToolListBuffer, + layer1, layer2 ); + + if( FullFileName != wxEmptyString ) + { + dest = wxFopen( FullFileName, wxT( "w" ) ); + if( dest == 0 ) + { + msg = _( "Unable to create file " ) + FullFileName; + DisplayError( this, msg ); + EndModal( 0 ); + return; + } + + Create_Drill_File_EXCELLON( s_HoleListBuffer, s_ToolListBuffer ); } - /* Init : */ - Affiche_1_Parametre( m_Parent, 0, _( "File" ), FullFileName, BLUE ); + switch( m_Choice_Drill_Map->GetSelection() ) + { + case 0: + break; - setlocale( LC_NUMERIC, "C" ); // Use the standard notation for float numbers - Init_Drill(); + case 1: + GenDrillMap( FullFileName, + s_HoleListBuffer, + s_ToolListBuffer, + PLOT_FORMAT_HPGL ); + break; - ii = Gen_Liste_Tools( s_ToolListBuffer, TRUE ); + case 2: + GenDrillMap( FullFileName, + s_HoleListBuffer, + s_ToolListBuffer, + PLOT_FORMAT_POST ); + break; + } - msg.Printf( wxT( "%d" ), ii ); - Affiche_1_Parametre( m_Parent, 30, _( "Tools" ), msg, BROWN ); + if( m_Choice_Drill_Report->GetSelection() > 0 ) + GenDrillReport( FullFileName, s_ToolListBuffer ); - ii = Create_Drill_File_EXCELLON( s_ToolListBuffer ); - msg.Printf( wxT( "%d" ), ii ); - Affiche_1_Parametre( m_Parent, 45, _( "Drill" ), msg, GREEN ); + if( !ExistsBuriedVias ) + break; - Write_End_Of_File_Drill(); - setlocale( LC_NUMERIC, "" ); // Revert to locale float notation + if( layer2 >= LAYER_CMP_N ) // no more layer pair to consider + break; + layer1++; layer2++; // use next layer pair + if( layer2 == g_DesignSettings.m_CopperLayerCount - 1 ) // The last layer is reached + layer2 = LAYER_CMP_N; // the last layer is always the component layer } - switch( m_Choice_Drill_Map->GetSelection() ) - { - case 0: - break; - - case 1: - GenDrillMap( s_ToolListBuffer, PLOT_FORMAT_HPGL ); - break; - - case 2: - GenDrillMap( s_ToolListBuffer, PLOT_FORMAT_POST ); - break; - } - - if( m_Choice_Drill_Report->GetSelection() > 0 ) - GenDrillReport( s_ToolListBuffer ); - EndModal( 0 ); } @@ -396,181 +382,166 @@ void WinEDA_DrillFrame::UpdatePrecisionOptions( wxCommandEvent& event ) /**********************************************************************************/ -int WinEDA_DrillFrame::Create_Drill_File_EXCELLON( std::vector& buffer ) +int WinEDA_DrillFrame::Create_Drill_File_EXCELLON( std::vector& aHoleListBuffer, + std::vector& aToolListBuffer ) /**********************************************************************************/ -/* Create the drill file in EXCELLON format - * Return hole count - * buffer: Drill tools list +/** + * Create the drill file in EXCELLON format + * @return hole count + * @param aHoleListBuffer = hole descriptor list + * @param aToolListBuffer = Drill tools list */ { - TRACK* pt_piste; - D_PAD* pt_pad; - MODULE* Module; - int diam, holes_count; - int x0, y0, xf, yf, xc, yc; - float xt, yt; - char line[1024]; + int diam, holes_count; + int x0, y0, xf, yf, xc, yc; + float xt, yt; + char line[1024]; + + setlocale( LC_NUMERIC, "C" ); // Use the standard notation for float numbers + + Write_Excellon_Header( dest ); - /* Create the pad drill list : */ holes_count = 0; + int tool_reference = -2; - /* Read the hole file */ - for( unsigned ii = 0; ii < buffer.size(); ii++ ) + /* Write the tool list */ + for( unsigned ii = 0; ii < aToolListBuffer.size(); ii++ ) { - sprintf( line, "T%d\n", ii + 1 ); fputs( line, dest ); - /* Read the via list */ - { - pt_piste = m_Parent->m_Pcb->m_Track; - for( ; pt_piste != NULL; pt_piste = (TRACK*) pt_piste->Pnext ) - { - if( pt_piste->Type() != TYPEVIA ) - continue; - int via_drill = pt_piste->GetDrillValue(); - if( via_drill == 0 ) - continue; + if( s_Unit_Drill_is_Inch ) /* does it need T01, T02 or is T1,T2 ok?*/ + sprintf( line, "T%dC%.3f\n", ii + 1, + float (aToolListBuffer[ii].m_Diameter) * s_ConversionUnits ); + else + sprintf( line, "T%dC%.3f\n", ii + 1, + float (aToolListBuffer[ii].m_Diameter) * s_ConversionUnits * 10.0 ); - if( buffer[ii].m_Diameter != via_drill ) - continue; - - x0 = pt_piste->m_Start.x - File_Drill_Offset.x; - y0 = pt_piste->m_Start.y - File_Drill_Offset.y; - - if( !Mirror ) - y0 *= -1; - - xt = float (x0) * conv_unit; yt = float (y0) * conv_unit; - if( s_Unit_Drill_is_Inch ) - { - Gen_Line_EXCELLON( line, xt, yt ); - } - else - { - /* metric 3:3 */ - Gen_Line_EXCELLON( line, xt * 10, yt * 10 ); - } - - fputs( line, dest ); - holes_count++; - } - } - - /* Read pad list and create Drill infos for round holes only: */ - Module = m_Parent->m_Pcb->m_Modules; - for( ; Module != NULL; Module = (MODULE*) Module->Pnext ) - { - /* Read and analyse pads */ - pt_pad = (D_PAD*) Module->m_Pads; - for( ; pt_pad != NULL; pt_pad = (D_PAD*) pt_pad->Pnext ) - { - if( pt_pad->m_DrillShape != PAD_CIRCLE ) - continue; - diam = pt_pad->m_Drill.x; - if( diam == 0 ) - continue; - if( diam != buffer[ii].m_Diameter ) - continue; - - /* Compute the hole coordinates: */ - x0 = pt_pad->m_Pos.x - File_Drill_Offset.x; - y0 = pt_pad->m_Pos.y - File_Drill_Offset.y; - - if( !Mirror ) - y0 *= -1; - - xt = float (x0) * conv_unit; yt = float (y0) * conv_unit; - if( s_Unit_Drill_is_Inch ) - Gen_Line_EXCELLON( line, xt, yt ); - else - Gen_Line_EXCELLON( line, xt * 10, yt * 10 ); - - fputs( line, dest ); - holes_count++; - } - - /* ens analyse one module */ - } - - // End analyse module list - - - /* Read pad list and create Drill infos for oblong holes only: */ - Module = m_Parent->m_Pcb->m_Modules; - for( ; Module != NULL; Module = (MODULE*) Module->Pnext ) - { - /* Analyse pad list for the module */ - pt_pad = (D_PAD*) Module->m_Pads; - for( ; pt_pad != NULL; pt_pad = (D_PAD*) pt_pad->Pnext ) - { - if( pt_pad->m_DrillShape != PAD_OVAL ) - continue; - - diam = MIN( pt_pad->m_Drill.x, pt_pad->m_Drill.y ); - if( diam == 0 ) - continue; - if( diam != buffer[ii].m_Diameter ) - continue; - - /* Compute the hole coordinates: */ - xc = x0 = xf = pt_pad->m_Pos.x - File_Drill_Offset.x; - yc = y0 = yf = pt_pad->m_Pos.y - File_Drill_Offset.y; - - /* Compute the start and end coordinates for the shape */ - if( pt_pad->m_Drill.x < pt_pad->m_Drill.y ) - { - int delta = (pt_pad->m_Drill.y - pt_pad->m_Drill.x) / 2; - y0 -= delta; yf += delta; - } - else - { - int delta = (pt_pad->m_Drill.x - pt_pad->m_Drill.y) / 2; - x0 -= delta; xf += delta; - } - RotatePoint( &x0, &y0, xc, yc, pt_pad->m_Orient ); - RotatePoint( &xf, &yf, xc, yc, pt_pad->m_Orient ); - - - if( !Mirror ) - { - y0 *= -1; yf *= -1; - } - - xt = float (x0) * conv_unit; yt = float (y0) * conv_unit; - if( s_Unit_Drill_is_Inch ) - Gen_Line_EXCELLON( line, xt, yt ); - else - Gen_Line_EXCELLON( line, xt * 10, yt * 10 ); - /* remove the '\n' from end of line, because we must add the "G85" command to the line: */ - for( int kk = 0; line[kk] != 0; kk++ ) - if( line[kk] == '\n' || line[kk] =='\r' ) - line[kk] = 0; - - fputs( line, dest ); - - fputs( "G85", dest ); // add the "G85" command - - xt = float (xf) * conv_unit; yt = float (yf) * conv_unit; - if( s_Unit_Drill_is_Inch ) - Gen_Line_EXCELLON( line, xt, yt ); - else - Gen_Line_EXCELLON( line, xt * 10, yt * 10 ); - fputs( "G05\n", dest ); - holes_count++; - } - - /* End Analyse pad list for the module */ - } - - /* End analyse modules for the current tool */ + fputs( line, dest ); } + fputs( "%\n", dest ); + + if( !Minimal ) + fputs( "M47\n", dest ); /* Operator message */ + fputs( "G05\n", dest ); /* Drill mode */ + /* Units : */ + if( s_Unit_Drill_is_Inch && !Minimal ) + fputs( "M72\n", dest ); /* M72 = inch mode */ + else if( !Minimal ) + fputs( "M71\n", dest ); /* M71 = metric mode */ + + /* Read the hole file and generate lines for normal holes (oblong holes will be created later) */ + for( unsigned ii = 0; ii < aHoleListBuffer.size(); ii++ ) + { + if( aHoleListBuffer[ii].m_Hole_Shape ) + continue; // oblong holes will be created later + if( tool_reference != aHoleListBuffer[ii].m_Tool_Reference ) + { + tool_reference = aHoleListBuffer[ii].m_Tool_Reference; + sprintf( line, "T%d\n", tool_reference ); + fputs( line, dest ); + } + + x0 = aHoleListBuffer[ii].m_Hole_Pos_X - File_Drill_Offset.x; + y0 = aHoleListBuffer[ii].m_Hole_Pos_Y - File_Drill_Offset.y; + + if( !Mirror ) + y0 *= -1; + + xt = float (x0) * s_ConversionUnits; yt = float (y0) * s_ConversionUnits; + if( s_Unit_Drill_is_Inch ) + { + Gen_Line_EXCELLON( line, xt, yt ); + } + else + { + /* metric 3:3 */ + Gen_Line_EXCELLON( line, xt * 10, yt * 10 ); + } + + fputs( line, dest ); + holes_count++; + } + + /* Read the hole file and generate lines for normal holes (oblong holes will be created later) */ + tool_reference = -2; // set to a value not used for aHoleListBuffer[ii].m_Tool_Reference + for( unsigned ii = 0; ii < aHoleListBuffer.size(); ii++ ) + { + if( aHoleListBuffer[ii].m_Hole_Shape == 0 ) + continue; // wait for oblong holes + if( tool_reference != aHoleListBuffer[ii].m_Tool_Reference ) + { + tool_reference = aHoleListBuffer[ii].m_Tool_Reference; + sprintf( line, "T%d\n", tool_reference ); + fputs( line, dest ); + } + + diam = MIN( aHoleListBuffer[ii].m_Hole_SizeX, aHoleListBuffer[ii].m_Hole_SizeY ); + if( diam == 0 ) + continue; + + /* Compute the hole coordinates: */ + xc = x0 = xf = aHoleListBuffer[ii].m_Hole_Pos_X - File_Drill_Offset.x; + yc = y0 = yf = aHoleListBuffer[ii].m_Hole_Pos_Y - File_Drill_Offset.y; + + /* Compute the start and end coordinates for the shape */ + if( aHoleListBuffer[ii].m_Hole_SizeX < aHoleListBuffer[ii].m_Hole_SizeY ) + { + int delta = (aHoleListBuffer[ii].m_Hole_SizeY - aHoleListBuffer[ii].m_Hole_SizeX) / 2; + y0 -= delta; yf += delta; + } + else + { + int delta = (aHoleListBuffer[ii].m_Hole_SizeX - aHoleListBuffer[ii].m_Hole_SizeY ) / 2; + x0 -= delta; xf += delta; + } + RotatePoint( &x0, &y0, xc, yc, aHoleListBuffer[ii].m_Hole_Orient ); + RotatePoint( &xf, &yf, xc, yc, aHoleListBuffer[ii].m_Hole_Orient ); + + + if( !Mirror ) + { + y0 *= -1; yf *= -1; + } + + xt = float (x0) * s_ConversionUnits; yt = float (y0) * s_ConversionUnits; + if( s_Unit_Drill_is_Inch ) + Gen_Line_EXCELLON( line, xt, yt ); + else + Gen_Line_EXCELLON( line, xt * 10, yt * 10 ); + /* remove the '\n' from end of line, because we must add the "G85" command to the line: */ + for( int kk = 0; line[kk] != 0; kk++ ) + if( line[kk] == '\n' || line[kk] =='\r' ) + line[kk] = 0; + + fputs( line, dest ); + + fputs( "G85", dest ); // add the "G85" command + + xt = float (xf) * s_ConversionUnits; yt = float (yf) * s_ConversionUnits; + if( s_Unit_Drill_is_Inch ) + Gen_Line_EXCELLON( line, xt, yt ); + else + Gen_Line_EXCELLON( line, xt * 10, yt * 10 ); + fputs( "G05\n", dest ); + holes_count++; + } + + Write_End_Of_File_Drill( dest ); + + setlocale( LC_NUMERIC, "" ); // Revert to locale float notation + return holes_count; } -/*****************************************************/ +/***********************************************************************/ void Gen_Line_EXCELLON( char* line, float x, float y ) -/*****************************************************/ +/***********************************************************************/ + +/* Created a line like: + * X48000Y19500 + * According to the selected format + */ { wxString xs, ys; int xpad = s_Precision.m_lhs + s_Precision.m_rhs; @@ -640,211 +611,87 @@ void Gen_Line_EXCELLON( char* line, float x, float y ) } -/*************************************************************************/ -int GetOrAddForet( std::vector& buffer, int diameter ) -/*************************************************************************/ +/************************************************************/ +void WinEDA_DrillFrame::Write_Excellon_Header( FILE* aFile ) +/************************************************************/ -/* Search the drill tool for the diameter "diameter" - * Create a new one if not found - * return the index in buffer +/* Print the DRILL file header. The full header is: + * M48 + * ;DRILL file {PCBNEW (2007-11-29-b)} date 17/1/2008-21:02:35 + * ;FORMAT={2:4 / absolute / Pouces / Suppression zeros de tête} + * R,T + * VER,1 + * FMAT,2 + * INCH,TZ + * TCST,OFF + * ICI,OFF + * ATC,ON */ -{ - unsigned ii; - - if( diameter == 0 ) - return -1; - - /* Search for an existing tool: */ - for( ii = 0; ii < buffer.size(); ii++ ) - { - if( buffer[ii].m_Diameter == diameter ) /* found */ - return ii; - } - - /* No tool found, we must create a new one */ - DRILL_TOOL new_tool( diameter ); - buffer.push_back( new_tool ); - return buffer.size() - 1; -} - - -/*********************************************************************************************/ -int WinEDA_DrillFrame::Gen_Liste_Tools( std::vector& buffer, bool print_header ) -/*********************************************************************************************/ - -/* Etablit la liste des drill_tools de percage, dans l'ordre croissant des - * diametres - * Retourne: - * Nombre de Forets - * - * Fills the list of tools buffer - */ -{ - D_PAD* pt_pad; - MODULE* Module; - unsigned ii; - int diam; - char line[1024]; - - buffer.clear(); - - /* Creates the via tools list*/ - TRACK* pt_piste = m_Parent->m_Pcb->m_Track; - - for( ; pt_piste != NULL; pt_piste = (TRACK*) pt_piste->Pnext ) - { - if( pt_piste->Type() != TYPEVIA ) - continue; - int via_drill = pt_piste->GetDrillValue(); - if( via_drill == 0 ) - continue; - - ii = GetOrAddForet( buffer, via_drill ); - if ( ii >= 0 ) - buffer[ii].m_TotalCount++; - } - - /* Create the pad tools : */ - Module = m_Parent->m_Pcb->m_Modules; - for( ; Module != NULL; Module = (MODULE*) Module->Pnext ) - { - /* See the pad list for hole sizes */ - pt_pad = (D_PAD*) Module->m_Pads; - for( ; pt_pad != NULL; pt_pad = (D_PAD*) pt_pad->Pnext ) - { - if( pt_pad->m_DrillShape == PAD_CIRCLE ) - diam = pt_pad->m_Drill.x; - else - diam = MIN( pt_pad->m_Drill.x, pt_pad->m_Drill.y ); - - if( diam == 0 ) - continue; - - ii = GetOrAddForet( buffer, diam ); - if ( ii >= 0 ) - { - buffer[ii].m_TotalCount++; - if( pt_pad->m_DrillShape == PAD_OVAL ) - buffer[ii].m_OvalCount++; - } - } - } - - /* Sort drill_tools by increasing size */ - sort( buffer.begin(), buffer.end(), CmpDrillDiameterTool ); - - /* Write the tool list in excellon file */ - if( print_header ) - { - for( ii = 0; ii < buffer.size(); ii++ ) - { - if( s_Unit_Drill_is_Inch ) /* does it need T01, T02 or is T1,T2 ok?*/ - sprintf( line, "T%dC%.3f\n", ii + 1, - float (buffer[ii].m_Diameter) * conv_unit ); - else - sprintf( line, "T%dC%.3f\n", ii + 1, - float (buffer[ii].m_Diameter) * conv_unit * 10.0 ); - - fputs( line, dest ); - } - - fputs( "%\n", dest ); - if( !Minimal ) - fputs( "M47\n", dest ); /* Operator message */ - fputs( "G05\n", dest ); /* Drill mode */ - /* Units : */ - if( s_Unit_Drill_is_Inch && !Minimal ) - fputs( "M72\n", dest ); /* M72 = inch mode */ - else if( !Minimal ) - fputs( "M71\n", dest ); /* M71 = metric mode */ - } - - return buffer.size(); -} - - -/***************************************/ -void WinEDA_DrillFrame::Init_Drill() -/***************************************/ -/* Print the DRILL file header */ { char Line[256]; - fputs( "M48\n", dest ); + fputs( "M48\n", aFile ); if( !Minimal ) { DateAndTime( Line ); wxString Title = g_Main_Title + wxT( " " ) + GetBuildVersion(); fprintf( dest, ";DRILL file {%s} date %s\n", CONV_TO_UTF8( Title ), Line ); - fputs( ";FORMAT={", dest ); + fputs( ";FORMAT={", aFile ); fprintf( dest, "%s / absolute / ", CONV_TO_UTF8( m_Choice_Precision->GetStringSelection() ) ); fprintf( dest, "%s / ", CONV_TO_UTF8( m_Choice_Unit->GetStringSelection() ) ); fprintf( dest, "%s}\n", CONV_TO_UTF8( m_Choice_Zeros_Format->GetStringSelection() ) ); - fputs( "R,T\nVER,1\nFMAT,2\n", dest ); + fputs( "R,T\nVER,1\nFMAT,2\n", aFile ); } if( s_Unit_Drill_is_Inch ) - fputs( "INCH", dest ); // Si unites en INCHES + fputs( "INCH", aFile ); // Si unites en INCHES else - fputs( "METRIC", dest ); // Si unites en mm + fputs( "METRIC", aFile ); // Si unites en mm switch( s_Zeros_Format ) { case SUPPRESS_LEADING: case DECIMAL_FORMAT: - fputs( ",TZ\n", dest ); + fputs( ",TZ\n", aFile ); break; case SUPPRESS_TRAILING: - fputs( ",LZ\n", dest ); + fputs( ",LZ\n", aFile ); break; case KEEP_ZEROS: - fputs( ",TZ\n", dest ); // TZ is acceptable when all zeros are kept + fputs( ",TZ\n", aFile ); // TZ is acceptable when all zeros are kept break; } if( !Minimal ) - fputs( "TCST,OFF\nICI,OFF\nATC,ON\n", dest ); + fputs( "TCST,OFF\nICI,OFF\nATC,ON\n", aFile ); } -/*****************************/ -void Write_End_Of_File_Drill() -/*****************************/ +/****************************************/ +void Write_End_Of_File_Drill( FILE* aFile ) +/****************************************/ { //add if minimal here - fputs( "T0\nM30\n", dest ); fclose( dest ); + fputs( "T0\nM30\n", aFile ); fclose( aFile ); } /**********************************************************************************/ -void WinEDA_DrillFrame::GenDrillMap( std::vector& buffer, int format ) +void WinEDA_DrillFrame::GenDrillMap( const wxString aFileName, + std::vector& aHoleListBuffer, + std::vector& buffer, int format ) /**********************************************************************************/ /* Genere le plan de percage (Drill map) format HPGL ou POSTSCRIPT */ { - unsigned ii; - int x, y; - int plotX, plotY, TextWidth; - int intervalle = 0, CharSize = 0; - EDA_BaseStruct* PtStruct; - int old_g_PlotOrient = g_PlotOrient; - wxString FullFileName, Mask( wxT( "*" ) ), Ext; - char line[1024]; - int dX, dY; - wxPoint BoardCentre; - int PlotMarge_in_mils = 400; // Margin in 1/1000 inch - int marge = PlotMarge_in_mils * U_PCB; - wxSize SheetSize; - float fTextScale = 1.0; - double scale_x = 1.0, scale_y = 1.0; - Ki_PageDescr* SheetPS = NULL; - wxString msg; + wxString FullFileName, Mask( wxT( "*" ) ), Ext; + wxString msg; /* Init extension */ switch( format ) @@ -863,7 +710,7 @@ void WinEDA_DrillFrame::GenDrillMap( std::vector& buffer, int format } /* Init file name */ - FullFileName = m_Parent->m_CurrentScreen->m_FileName; + FullFileName = aFileName; ChangeFileNameExt( FullFileName, Ext ); Mask += Ext; @@ -879,630 +726,37 @@ void WinEDA_DrillFrame::GenDrillMap( std::vector& buffer, int format if( FullFileName.IsEmpty() ) return; - setlocale( LC_NUMERIC, "C" ); // Use the standard notation for float numbers - g_PlotOrient = 0; - /* calcul des dimensions et centre du PCB */ - m_Parent->m_Pcb->ComputeBoundaryBox(); - - dX = m_Parent->m_Pcb->m_BoundaryBox.GetWidth(); - dY = m_Parent->m_Pcb->m_BoundaryBox.GetHeight(); - BoardCentre = m_Parent->m_Pcb->m_BoundaryBox.Centre(); - - // Calcul de l'echelle du dessin du PCB, - // Echelle 1 en HPGL, dessin sur feuille A4 en PS, + texte description des symboles - switch( format ) - { - case PLOT_FORMAT_HPGL: /* Calcul des echelles de conversion format HPGL */ - Scale_X = Scale_Y = 1.0; - scale_x = Scale_X * SCALE_HPGL; - scale_y = Scale_Y * SCALE_HPGL; - fTextScale = SCALE_HPGL; - SheetSize = m_Parent->m_CurrentScreen->m_CurrentSheet->m_Size; - SheetSize.x *= U_PCB; - SheetSize.y *= U_PCB; - g_PlotOffset.x = 0; - g_PlotOffset.y = (int) (SheetSize.y * scale_y); - break; - - case PLOT_FORMAT_POST: - { - // calcul en unites internes des dimensions de la feuille ( connues en 1/1000 pouce ) - SheetPS = &g_Sheet_A4; - SheetSize.x = SheetPS->m_Size.x * U_PCB; - SheetSize.y = SheetPS->m_Size.y * U_PCB; - float Xscale = (float) ( SheetSize.x - (marge * 2) ) / dX; - float Yscale = (float) ( SheetSize.y * 0.6 - (marge * 2) ) / dY; - - scale_x = scale_y = MIN( Xscale, Yscale ); - - g_PlotOffset.x = -(SheetSize.x / 2) + - (int) (BoardCentre.x * scale_x) + marge; - g_PlotOffset.y = SheetSize.y / 2 + - (int) (BoardCentre.y * scale_y) - marge; - g_PlotOffset.y += SheetSize.y / 8; /* decalage pour legende */ - break; - } - } - dest = wxFopen( FullFileName, wxT( "wt" ) ); if( dest == 0 ) { - msg.Printf( _( "Unable to create file <%s>" ), FullFileName.GetData() ); + msg = _( "Unable to create file" ); + msg << wxT( " <" ) << FullFileName << wxT( ">" ); DisplayError( this, msg ); return; } - /* Init : */ - m_Parent->MsgPanel->EraseMsgBox(); - Affiche_1_Parametre( m_Parent, 0, _( "File" ), FullFileName, BLUE ); - - /* Calcul de la liste des diametres de percage (liste des drill_tools) */ - ii = Gen_Liste_Tools( s_ToolListBuffer, FALSE ); - msg.Printf( wxT( "%d" ), ii ); - Affiche_1_Parametre( m_Parent, 48, _( "Tools" ), msg, BROWN ); - - - switch( format ) - { - case PLOT_FORMAT_HPGL: - InitPlotParametresHPGL( g_PlotOffset, scale_x, scale_y ); - PrintHeaderHPGL( dest, g_HPGL_Pen_Speed, g_HPGL_Pen_Num ); - break; - - case PLOT_FORMAT_POST: - { - int BBox[4]; - BBox[0] = BBox[1] = PlotMarge_in_mils; - BBox[2] = SheetPS->m_Size.x - PlotMarge_in_mils; - BBox[3] = SheetPS->m_Size.y - PlotMarge_in_mils; - InitPlotParametresPS( g_PlotOffset, SheetPS, - (double) 1.0 / PCB_INTERNAL_UNIT, (double) 1.0 / PCB_INTERNAL_UNIT ); - SetDefaultLineWidthPS( 10 ); // Set line with to 10/1000 inch - PrintHeaderPS( dest, wxT( "PCBNEW-PS" ), FullFileName, 1, BBox, wxLANDSCAPE ); - InitPlotParametresPS( g_PlotOffset, SheetPS, scale_x, scale_y ); - } - break; - - default: - break; - } - - /* Draw items on edge layer */ - PtStruct = m_Parent->m_Pcb->m_Drawings; - for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext ) - { - switch( PtStruct->Type() ) - { - case TYPEDRAWSEGMENT: - PlotDrawSegment( (DRAWSEGMENT*) PtStruct, format, EDGE_LAYER ); - break; - - case TYPETEXTE: - PlotTextePcb( (TEXTE_PCB*) PtStruct, format, EDGE_LAYER ); - break; - - case TYPECOTATION: - PlotCotation( (COTATION*) PtStruct, format, EDGE_LAYER ); - break; - - case TYPEMIRE: - PlotMirePcb( (MIREPCB*) PtStruct, format, EDGE_LAYER ); - break; - - case TYPEMARKER: // do not draw - break; - - default: - DisplayError( this, wxT( "WinEDA_DrillFrame::GenDrillMap() : Unexpected Draw Type" ) ); - break; - } - } - - TextWidth = 50; // Set Drill Symbols width in 1/10000 mils - - if( format == PLOT_FORMAT_POST ) - { - sprintf( line, "%d setlinewidth\n", TextWidth ); - fputs( line, dest ); - } - - ii = Plot_Drill_PcbMap( s_ToolListBuffer, format ); - msg.Printf( wxT( "%d" ), ii ); - Affiche_1_Parametre( m_Parent, 64, _( "Drill" ), msg, GREEN ); - - /* Impression de la liste des symboles utilises */ - CharSize = 800; /* text size in 1/10000 mils */ - float CharScale = 1.0 / scale_x; /* real scale will be CharScale * scale_x, - * because the global plot scale is scale_x */ - TextWidth = (int) (50 * CharScale); // Set text width - intervalle = (int) (CharSize * CharScale) + TextWidth; - - switch( format ) - { - case PLOT_FORMAT_HPGL: - { - /* generation des dim: commande SI x,y; x et y = dim en cm */ - char csize[256]; - sprintf( csize, "%2.3f", (float) CharSize * CharScale * 0.000254 ); - sprintf( line, "SI %s, %s;\n", csize, csize ); - break; - } - - case PLOT_FORMAT_POST: - /* Reglage de l'epaisseur de traits des textes */ - sprintf( line, "%d setlinewidth\n", TextWidth ); - break; - - default: - *line = 0; - break; - } - - fputs( line, dest ); - - switch( format ) - { - default: - case PLOT_FORMAT_POST: - g_PlotOffset.x = 0; - g_PlotOffset.y = 0; - InitPlotParametresPS( g_PlotOffset, SheetPS, scale_x, scale_x ); - break; - - case PLOT_FORMAT_HPGL: - InitPlotParametresHPGL( g_PlotOffset, scale_x, scale_x ); - break; - } - - /* Trace des informations */ - - /* Trace de "Infos" */ - plotX = marge + 1000; - plotY = CharSize + 1000; - x = plotX; y = plotY; - x = +g_PlotOffset.x + (int) (x * fTextScale); - y = g_PlotOffset.y - (int) (y * fTextScale); - - plotY += (int) ( intervalle * 1.2) + 200; - - switch( format ) - { - case PLOT_FORMAT_HPGL: - sprintf( line, "PU %d, %d; LBInfos\03;\n", - x + (int) (intervalle * CharScale * fTextScale), - y - (int) (CharSize / 2 * CharScale * fTextScale) ); - fputs( line, dest ); - break; - - case PLOT_FORMAT_POST: - wxString Text = wxT( "Infos" ); - Plot_1_texte( format, Text, 0, TextWidth, - x, y, - (int) (CharSize * CharScale), (int) (CharSize * CharScale), - FALSE ); - break; - } - - - for( ii = 0; ii < buffer.size(); ii++ ) - { - int plot_diam; - if( buffer[ii].m_TotalCount == 0 ) - continue; - - plot_diam = (int) (buffer[ii].m_Diameter); - x = plotX; y = plotY; - x = -g_PlotOffset.x + (int) (x * fTextScale); - y = g_PlotOffset.y - (int) (y * fTextScale); - PlotDrillSymbol( wxPoint( x, y ), plot_diam, ii, format ); - - intervalle = (int) (CharSize * CharScale) + TextWidth; - intervalle = (int) ( intervalle * 1.2); - - if( intervalle < (plot_diam + 200 + TextWidth) ) - intervalle = plot_diam + 200 + TextWidth; - - int rayon = plot_diam / 2; - x = plotX + rayon + (int) (CharSize * CharScale); y = plotY; - x = -g_PlotOffset.x + (int) (x * fTextScale); - y = g_PlotOffset.y - (int) (y * fTextScale); - - /* Trace de la legende associee */ - switch( format ) - { - case PLOT_FORMAT_HPGL: - - // List the diameter of each drill in the selected Drill Unit, - // and then its diameter in the other Drill Unit. - if( s_Unit_Drill_is_Inch ) - sprintf( line, "PU %d, %d; LB%2.3f\" / %2.2fmm ", - x + (int) (intervalle * CharScale * fTextScale), - y - (int) (CharSize / 2 * CharScale * fTextScale), - float (buffer[ii].m_Diameter) * 0.0001, - float (buffer[ii].m_Diameter) * 0.00254 ); - else - sprintf( line, "PU %d, %d; LB%2.2fmm / %2.3f\" ", - x + (int) (intervalle * CharScale * fTextScale), - y - (int) (CharSize / 2 * CharScale * fTextScale), - float (buffer[ii].m_Diameter) * 0.00254, - float (buffer[ii].m_Diameter) * 0.0001 ); - fputs( line, dest ); - - // Now list how many holes and ovals are associated with each drill. - if( ( buffer[ii].m_TotalCount == 1 ) && ( buffer[ii].m_OvalCount == 0 ) ) - sprintf( line, "(1 hole)\n" ); - else if( buffer[ii].m_TotalCount == 1 ) // && ( buffer[ii]m_OvalCount == 1 ) - sprintf( line, "(1 hole) (with 1 oblong)\n" ); - else if( buffer[ii].m_OvalCount == 0 ) - sprintf( line, "(%d holes)\n", - buffer[ii].m_TotalCount ); - else if( buffer[ii].m_OvalCount == 1 ) - sprintf( line, "(%d holes) (with 1 oblong)\n", - buffer[ii].m_TotalCount ); - else // if ( buffer[ii]m_OvalCount > 1 ) - sprintf( line, "(%d holes) (with %d oblongs)\n", - buffer[ii].m_TotalCount, - buffer[ii].m_OvalCount ); - fputs( line, dest ); - fputs( "\03;\n", dest ); - break; - - case PLOT_FORMAT_POST: - - // List the diameter of each drill in the selected Drill Unit, - // and then its diameter in the other Drill Unit. - if( s_Unit_Drill_is_Inch ) - sprintf( line, "%2.3f\" / %2.2fmm ", - float (buffer[ii].m_Diameter) * 0.0001, - float (buffer[ii].m_Diameter) * 0.00254 ); - else - sprintf( line, "%2.2fmm / %2.3f\" ", - float (buffer[ii].m_Diameter) * 0.00254, - float (buffer[ii].m_Diameter) * 0.0001 ); - msg = CONV_FROM_UTF8( line ); - - // Now list how many holes and ovals are associated with each drill. - if( ( buffer[ii].m_TotalCount == 1 ) && ( buffer[ii].m_OvalCount == 0 ) ) - sprintf( line, "(1 hole)" ); - else if( buffer[ii].m_TotalCount == 1 ) // && ( buffer[ii]m_OvalCount == 1 ) - sprintf( line, "(1 hole) (with 1 oblong)" ); - else if( buffer[ii].m_OvalCount == 0 ) - sprintf( line, "(%d holes)", - buffer[ii].m_TotalCount ); - else if( buffer[ii].m_OvalCount == 1 ) - sprintf( line, "(%d holes) (with 1 oblong)", - buffer[ii].m_TotalCount ); - else // if ( buffer[ii]m_OvalCount > 1 ) - sprintf( line, "(%d holes) (with %d oblongs)", - buffer[ii].m_TotalCount, - buffer[ii].m_OvalCount ); - msg += CONV_FROM_UTF8( line ); - Plot_1_texte( format, msg, 0, TextWidth, - x, y, - (int) (CharSize * CharScale), - (int) (CharSize * CharScale), - FALSE ); - break; - } - - plotY += intervalle; - } - - switch( format ) - { - case PLOT_FORMAT_HPGL: - CloseFileHPGL( dest ); - break; - - case PLOT_FORMAT_POST: - CloseFilePS( dest ); - break; - } - - setlocale( LC_NUMERIC, "" ); // Revert to local notation for float numbers - - g_PlotOrient = old_g_PlotOrient; + GenDrillMapFile( m_Parent->m_Pcb, + dest, + FullFileName, + m_Parent->m_CurrentScreen->m_CurrentSheet->m_Size, + s_HoleListBuffer, + s_ToolListBuffer, + s_Unit_Drill_is_Inch, + format ); } -/****************************************************************************************/ -int WinEDA_DrillFrame::Plot_Drill_PcbMap( std::vector& buffer, int format ) -/****************************************************************************************/ - -/** Creates the drill map file in HPGL or POSTSCRIPT format - * @return drill count - * @param buffer = drill list buffer - * @param format = ouput format (hpgl / ps) - */ -{ - TRACK* pt_piste; - D_PAD* pt_pad; - MODULE* Module; - unsigned shape_id; - int diam, holes_count; - wxPoint pos; - wxSize size; - - holes_count = 0; - - /* create the drill list */ - if( buffer.size() > 13 ) - { - DisplayInfo( this, - _( - " Drill map: Too many diameter values to draw to draw one symbol per drill value (max 13)\nPlot uses circle shape for some drill values" ), - 10 ); - } - - // Plot the drill map: - for( shape_id = 0; shape_id < buffer.size(); shape_id++ ) - { - /* create the via drill map */ - { - pt_piste = m_Parent->m_Pcb->m_Track; - for( ; pt_piste != NULL; pt_piste = (TRACK*) pt_piste->Pnext ) - { - if( pt_piste->Type() != TYPEVIA ) - continue; - int via_drill = pt_piste->GetDrillValue(); - if( via_drill != buffer[shape_id].m_Diameter ) - continue; - pos = pt_piste->m_Start; - PlotDrillSymbol( pos, via_drill, shape_id, format ); - - holes_count++; - } - } - /* create the pad drill map: */ - for( Module = m_Parent->m_Pcb->m_Modules; Module != NULL; Module = Module->Next() ) - { - pt_pad = (D_PAD*) Module->m_Pads; - for( ; pt_pad != NULL; pt_pad = pt_pad->Next() ) - { - switch( pt_pad->m_DrillShape ) - { - case PAD_CIRCLE: - diam = pt_pad->m_Drill.x; - if( diam != buffer[shape_id].m_Diameter ) - continue; - PlotDrillSymbol( pt_pad->m_Pos, diam, shape_id, format ); - break; - - case PAD_OVAL: - if( pt_pad->m_DrillShape != PAD_OVAL ) - continue; - diam = MIN( pt_pad->m_Drill.x, pt_pad->m_Drill.y ); - if( diam != buffer[shape_id].m_Diameter ) - continue; - PlotOvalDrillSymbol( pt_pad->m_Pos, pt_pad->m_Drill, pt_pad->m_Orient, format ); - break; - } - - holes_count++; - } - - /* Fin examen 1 module */ - } - - /* Fin 1 passe de drill_tool */ - } - - /* fin analyse des trous de modules */ - - return holes_count; -} - - -/************************************************************************************/ -void PlotDrillSymbol( const wxPoint& position, int diametre, int num_forme, int format ) -/************************************************************************************/ - -/* Trace un motif de numero de forme num_forme, aux coord x0, y0. - * x0, y0 = coordonnees tables - * diametre = diametre (coord table) du trou - * num_forme = index ( permet de generer des formes caract ) - */ -{ - int rayon = diametre / 2; - - void (*FctPlume)( wxPoint pos, int state ); - int x0, y0; - - x0 = position.x; y0 = position.y; - FctPlume = Move_Plume_HPGL; - if( format == PLOT_FORMAT_POST ) - FctPlume = LineTo_PS; - - switch( num_forme ) - { - case 0: /* vias : forme en X */ - FctPlume( wxPoint( x0 - rayon, y0 - rayon ), 'U' ); - FctPlume( wxPoint( x0 + rayon, y0 + rayon ), 'D' ); - FctPlume( wxPoint( x0 + rayon, y0 - rayon ), 'U' ); - FctPlume( wxPoint( x0 - rayon, y0 + rayon ), 'D' ); - break; - - case 1: /* Cercle */ - if( format == PLOT_FORMAT_HPGL ) - trace_1_pastille_RONDE_HPGL( wxPoint( x0, y0 ), diametre, FILAIRE ); - if( format == PLOT_FORMAT_POST ) - trace_1_pastille_RONDE_POST( wxPoint( x0, y0 ), diametre, FILAIRE ); - break; - - case 2: /* forme en + */ - FctPlume( wxPoint( x0, y0 - rayon ), 'U' ); - FctPlume( wxPoint( x0, y0 + rayon ), 'D' ); - FctPlume( wxPoint( x0 + rayon, y0 ), 'U' ); - FctPlume( wxPoint( x0 - rayon, y0 ), 'D' ); - break; - - case 3: /* forme en X cercle */ - FctPlume( wxPoint( x0 - rayon, y0 - rayon ), 'U' ); - FctPlume( wxPoint( x0 + rayon, y0 + rayon ), 'D' ); - FctPlume( wxPoint( x0 + rayon, y0 - rayon ), 'U' ); - FctPlume( wxPoint( x0 - rayon, y0 + rayon ), 'D' ); - if( format == PLOT_FORMAT_HPGL ) - trace_1_pastille_RONDE_HPGL( wxPoint( x0, y0 ), diametre, FILAIRE ); - if( format == PLOT_FORMAT_POST ) - trace_1_pastille_RONDE_POST( wxPoint( x0, y0 ), diametre, FILAIRE ); - break; - - case 4: /* forme en cercle barre de - */ - FctPlume( wxPoint( x0 - rayon, y0 ), 'U' ); - FctPlume( wxPoint( x0 + rayon, y0 ), 'D' ); - if( format == PLOT_FORMAT_HPGL ) - trace_1_pastille_RONDE_HPGL( wxPoint( x0, y0 ), diametre, FILAIRE ); - if( format == PLOT_FORMAT_POST ) - trace_1_pastille_RONDE_POST( wxPoint( x0, y0 ), diametre, FILAIRE ); - break; - - case 5: /* forme en cercle barre de | */ - FctPlume( wxPoint( x0, y0 - rayon ), 'U' ); - FctPlume( wxPoint( x0, y0 + rayon ), 'D' ); - if( format == PLOT_FORMAT_HPGL ) - trace_1_pastille_RONDE_HPGL( wxPoint( x0, y0 ), diametre, FILAIRE ); - if( format == PLOT_FORMAT_POST ) - trace_1_pastille_RONDE_POST( wxPoint( x0, y0 ), diametre, FILAIRE ); - break; - - case 6: /* forme en carre */ - if( format == PLOT_FORMAT_HPGL ) - trace_1_pad_TRAPEZE_HPGL( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, - 0 ), 0, - FILAIRE ); - if( format == PLOT_FORMAT_POST ) - trace_1_pad_TRAPEZE_POST( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, - 0 ), 0, - FILAIRE ); - break; - - case 7: /* forme en losange */ - if( format == PLOT_FORMAT_HPGL ) - trace_1_pad_TRAPEZE_HPGL( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, - 0 ), 450, - FILAIRE ); - if( format == PLOT_FORMAT_POST ) - trace_1_pad_TRAPEZE_POST( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, - 0 ), 450, - FILAIRE ); - break; - - case 8: /* forme en carre barre par un X*/ - FctPlume( wxPoint( x0 - rayon, y0 - rayon ), 'U' ); - FctPlume( wxPoint( x0 + rayon, y0 + rayon ), 'D' ); - FctPlume( wxPoint( x0 + rayon, y0 - rayon ), 'U' ); - FctPlume( wxPoint( x0 - rayon, y0 + rayon ), 'D' ); - if( format == PLOT_FORMAT_HPGL ) - trace_1_pad_TRAPEZE_HPGL( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, - 0 ), 0, - FILAIRE ); - if( format == PLOT_FORMAT_POST ) - trace_1_pad_TRAPEZE_POST( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, - 0 ), 0, - FILAIRE ); - break; - - case 9: /* forme en losange barre par un +*/ - FctPlume( wxPoint( x0, y0 - rayon ), 'U' ); - FctPlume( wxPoint( x0, y0 + rayon ), 'D' ); - FctPlume( wxPoint( x0 + rayon, y0 ), 'U' ); - FctPlume( wxPoint( x0 - rayon, y0 ), 'D' ); - if( format == PLOT_FORMAT_HPGL ) - trace_1_pad_TRAPEZE_HPGL( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, - 0 ), 450, - FILAIRE ); - if( format == PLOT_FORMAT_POST ) - trace_1_pad_TRAPEZE_POST( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, - 0 ), 450, - FILAIRE ); - break; - - case 10: /* forme en carre barre par un '/' */ - FctPlume( wxPoint( x0 - rayon, y0 - rayon ), 'U' ); - FctPlume( wxPoint( x0 + rayon, y0 + rayon ), 'D' ); - if( format == PLOT_FORMAT_HPGL ) - trace_1_pad_TRAPEZE_HPGL( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, - 0 ), 0, - FILAIRE ); - if( format == PLOT_FORMAT_POST ) - trace_1_pad_TRAPEZE_POST( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, - 0 ), 0, - FILAIRE ); - break; - - case 11: /* forme en losange barre par un |*/ - FctPlume( wxPoint( x0, y0 - rayon ), 'U' ); - FctPlume( wxPoint( x0, y0 + rayon ), 'D' ); - if( format == PLOT_FORMAT_HPGL ) - trace_1_pad_TRAPEZE_HPGL( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, - 0 ), 450, - FILAIRE ); - if( format == PLOT_FORMAT_POST ) - trace_1_pad_TRAPEZE_POST( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, - 0 ), 450, - FILAIRE ); - break; - - case 12: /* forme en losange barre par un -*/ - FctPlume( wxPoint( x0 - rayon, y0 ), 'U' ); - FctPlume( wxPoint( x0 + rayon, y0 ), 'D' ); - if( format == PLOT_FORMAT_HPGL ) - trace_1_pad_TRAPEZE_HPGL( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, - 0 ), 450, - FILAIRE ); - if( format == PLOT_FORMAT_POST ) - trace_1_pad_TRAPEZE_POST( wxPoint( x0, y0 ), wxSize( rayon, rayon ), wxSize( 0, - 0 ), 450, - FILAIRE ); - break; - - default: - if( format == PLOT_FORMAT_HPGL ) - trace_1_pastille_RONDE_HPGL( wxPoint( x0, y0 ), diametre, FILAIRE ); - if( format == PLOT_FORMAT_POST ) - trace_1_pastille_RONDE_POST( wxPoint( x0, y0 ), diametre, FILAIRE ); - break; - } - - if( format == PLOT_FORMAT_HPGL ) - Plume_HPGL( 'U' ); -} - - -/*********************************************************************************************/ -void PlotOvalDrillSymbol( const wxPoint& position, const wxSize& size, int orient, int format ) -/*********************************************************************************************/ - -/* Draws an oblong hole. - * because functions to draw oblong shapes exist to draw oblong pads, Use they. - */ -{ - switch( format ) - { - case PLOT_FORMAT_HPGL: - trace_1_pastille_OVALE_HPGL( position, size, orient, FILAIRE ); - break; - - case PLOT_FORMAT_POST: - trace_1_pastille_OVALE_POST( position, size, orient, FILAIRE ); - break; - } -} - - -/***************************************************************************/ -void WinEDA_DrillFrame::GenDrillReport( std::vector& buffer ) -/***************************************************************************/ +/**************************************************************************************************/ +void WinEDA_DrillFrame::GenDrillReport( const wxString aFileName, std::vector& buffer ) +/**************************************************************************************************/ /* * Create a list of drill values and drill count */ { wxString FileName, Mask( wxT( "*" ) ), Ext( wxT( ".rpt" ) ); - unsigned ii, TotalHoleCount; - char line[1024]; wxString msg; - FileName = m_Parent->m_CurrentScreen->m_FileName; + FileName = aFileName; ChangeFileNameExt( FileName, wxT( "-drl" ) + Ext ); Mask += Ext; @@ -1526,67 +780,5 @@ void WinEDA_DrillFrame::GenDrillReport( std::vector& buffer ) return; } - m_Parent->MsgPanel->EraseMsgBox(); - Affiche_1_Parametre( m_Parent, 0, _( "File" ), FileName, BLUE ); - - /* Determine the list of the different drill diameters. */ - ii = Gen_Liste_Tools( buffer, FALSE ); - msg.Printf( wxT( "%d" ), ii ); - Affiche_1_Parametre( m_Parent, 30, _( "Tools" ), msg, BROWN ); - - fprintf( dest, "Drill report for %s\n", CONV_TO_UTF8( m_Parent->m_CurrentScreen->m_FileName ) ); - - fprintf( dest, "Created on %s\n", DateAndTime( line ) ); - - // List which Drill Unit option had been selected for the associated drill file. - if( s_Unit_Drill_is_Inch ) - fputs( "Selected Drill Unit: Imperial (\")\n\n", dest ); - else - fputs( "Selected Drill Unit: Metric (mm)\n\n", dest ); - - TotalHoleCount = 0; - - for( ii = 0; ii < buffer.size(); ii++ ) - { - // List the tool number assigned to each drill, - // then its diameter in the selected Drill Unit, - // and then its diameter in the other Drill Unit. - if( s_Unit_Drill_is_Inch ) - sprintf( line, "T%d %2.3f\" %2.2fmm ", - ii + 1, - float (buffer[ii].m_Diameter) * 0.0001, - float (buffer[ii].m_Diameter) * 0.00254 ); - else - sprintf( line, "T%d %2.2fmm %2.3f\" ", - ii + 1, - float (buffer[ii].m_Diameter) * 0.00254, - float (buffer[ii].m_Diameter) * 0.0001 ); - fputs( line, dest ); - - // Now list how many holes and ovals are associated with each drill. - if( ( buffer[ii].m_TotalCount == 1 ) && ( buffer[ii].m_OvalCount == 0 ) ) - sprintf( line, "(1 hole)\n" ); - else if( buffer[ii].m_TotalCount == 1 ) - sprintf( line, "(1 hole) (with 1 oblong)\n" ); - else if( buffer[ii].m_OvalCount == 0 ) - sprintf( line, "(%d holes)\n", - buffer[ii].m_TotalCount ); - else if( buffer[ii].m_OvalCount == 1 ) - sprintf( line, "(%d holes) (with 1 oblong)\n", - buffer[ii].m_TotalCount ); - else // if ( buffer[ii]m_OvalCount > 1 ) - sprintf( line, "(%d holes) (with %d oblongs)\n", - buffer[ii].m_TotalCount, - buffer[ii].m_OvalCount ); - fputs( line, dest ); - - TotalHoleCount += buffer[ii].m_TotalCount; - } - - - - sprintf( line, "\ntotal holes count %d\n", TotalHoleCount ); - fputs( line, dest ); - - fclose( dest ); + GenDrillReportFile( dest, m_Parent->m_CurrentScreen->m_FileName, buffer, s_Unit_Drill_is_Inch ); } diff --git a/pcbnew/gendrill.h b/pcbnew/gendrill.h new file mode 100644 index 0000000000..99ec41bba6 --- /dev/null +++ b/pcbnew/gendrill.h @@ -0,0 +1,94 @@ +/*******************************************************************************/ +/* classes and functions declaration unsed in drill file and report generation */ +/*******************************************************************************/ + +#ifndef GENDRILL_H +#define GENDRILL_H + +/* the DRILL_TOOL class handle tools used in the excellon drill file */ +class DRILL_TOOL +{ +public: + int m_Diameter; // the diameter of the used tool (for oblong, the smaller size) + int m_TotalCount; // how many times it is used (round and oblong) + int m_OvalCount; // oblong count +public: + DRILL_TOOL( int diametre ) + { + m_TotalCount = 0; + m_OvalCount = 0; + m_Diameter = diametre; + } +}; + + +/* the HOLE_INFO class handle hole which must be drilled (diameter, position and layers) */ +class HOLE_INFO +{ +public: + int m_Hole_Diameter; // hole value, and for oblong min(hole size x, hole size y) + int m_Tool_Reference; // Tool reference for this hole = 1 ... n (values <=0 must not be used) + int m_Hole_SizeX; // hole size x for oblong holes + int m_Hole_SizeY; // hole size y for oblong holes + int m_Hole_Orient; // Hole rotation (= pad rotation) for oblong holes + int m_Hole_Shape; // hole shape: round (0) or oval (1) + int m_Hole_Pos_X; // hole position X + int m_Hole_Pos_Y; // hole position Y + int m_Hole_Bottom_Layer; // hole starting layer (usually copper) + int m_Hole_Top_Layer; // hole ending layer (usually component): m_Hole_First_Layer < m_Hole_Last_Layer +}; + + +/* the DrillPrecision class to handle drill precision format in excellon files*/ +class DrillPrecision +{ +public: + int m_lhs; + int m_rhs; + +public: + DrillPrecision( int l, int r ) { m_lhs = l; m_rhs = r; } +}; + +/* zeros format */ +enum zeros_fmt { + DECIMAL_FORMAT, + SUPPRESS_LEADING, + SUPPRESS_TRAILING, + KEEP_ZEROS +}; + + +/** + * Function BuildHolesList + * Create the list of holes and tools for a given board + * @param Pcb : the given board + * @param aHoleListBuffer : the std::vector to fill with pcb info + * @param aToolListBuffer : the std::vector to fill with tools to use + */ +void Build_Holes_List( BOARD* Pcb, std::vector& aHoleListBuffer, + std::vector& aToolListBuffer, + int aFirstLayer, int aLastLayer ); + + +void GenDrillMapFile( BOARD* aPcb, + FILE* aFile, + const wxString& aFullFileName, + wxSize aSheetSize, + std::vector aHoleListBuffer, + std::vector aToolListBuffer, + bool aUnit_Drill_is_Inch, + int format ); + +void Gen_Drill_PcbMap( BOARD* aPcb, FILE* aFile, + std::vector& aHoleListBuffer, + std::vector& aToolListBuffer, + int format ); + +/* + * Create a list of drill values and drill count + */ +void GenDrillReportFile( FILE* aFile, const wxString& aBoardFilename, + std::vector& aToolListBuffer, bool aUnit_Drill_is_Inch ); + +#endif // #ifndef GENDRILL_H diff --git a/pcbnew/makefile.include b/pcbnew/makefile.include index d1b037660c..6a71e17640 100644 --- a/pcbnew/makefile.include +++ b/pcbnew/makefile.include @@ -88,6 +88,8 @@ OBJECTS= $(TARGET).o classpcb.o\ librairi.o edgemod.o\ connect.o muonde.o attribut.o\ gendrill.o\ + gen_holes_and_tools_lists_for_drill.o\ + gen_drill_report_files.o\ sel_layer.o \ cotation.o\ automove.o\ diff --git a/pcbnew/onrightclick.cpp b/pcbnew/onrightclick.cpp index 63e7f99cf5..6c765ba042 100644 --- a/pcbnew/onrightclick.cpp +++ b/pcbnew/onrightclick.cpp @@ -657,14 +657,14 @@ void WinEDA_PcbFrame::createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu ADD_MENUITEM_WITH_SUBMENU( aPopMenu, zones_menu, -1, _( "Zones" ), add_zone_xpm ); int index; - if( ( index = edge_zone->HitTestForCorner( GetScreen()->m_Curseur ) ) >= 0 ) + if( ( index = edge_zone->HitTestForCorner( GetScreen()->RefPos( true ) ) ) >= 0 ) { ADD_MENUITEM( zones_menu, ID_POPUP_PCB_MOVE_ZONE_CORNER, _( "Move Corner" ), move_xpm ); ADD_MENUITEM( zones_menu, ID_POPUP_PCB_DELETE_ZONE_CORNER, _( "Delete Corner" ), delete_xpm ); } - else if( ( index = edge_zone->HitTestForEdge( GetScreen()->m_Curseur ) ) >= 0 ) + else if( ( index = edge_zone->HitTestForEdge( GetScreen()->RefPos( true ) ) ) >= 0 ) { ADD_MENUITEM( zones_menu, ID_POPUP_PCB_ADD_ZONE_CORNER, _( "Create Corner" ), Add_Corner_xpm ); diff --git a/pcbnew/tool_pcb.cpp b/pcbnew/tool_pcb.cpp index b86e08b0a7..00a9f37a10 100644 --- a/pcbnew/tool_pcb.cpp +++ b/pcbnew/tool_pcb.cpp @@ -611,6 +611,7 @@ WinEDAChoiceBox* WinEDA_PcbFrame::ReCreateLayerBox( WinEDA_Toolbar* parent ) /**************************************************************************/ { int ii, jj, ll; + unsigned lenght = 0; bool rebuild = FALSE; long current_mask_layer; @@ -679,10 +680,12 @@ WinEDAChoiceBox* WinEDA_PcbFrame::ReCreateLayerBox( WinEDA_Toolbar* parent ) msg = AddHotkeyName( msg, s_Board_Editor_Hokeys_Descr, HK_SwitchLayer[ii] ); m_SelLayerBox->Append( msg ); m_SelLayerBox->SetClientData( jj, (void*) ii ); + lenght = max(lenght, msg.Len() ); jj++; } } - + int lchar = m_SelLayerBox->GetFont().GetPointSize(); + m_SelLayerBox->SetSize(wxSize(lenght * lchar,-1)); m_SelLayerBox->SetToolTip( _( "+/- to switch" ) ); }