From 7d1c1f3085df2cdb33d8658bf9507078170a7bd6 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Mon, 14 Jul 2014 09:36:37 +0200 Subject: [PATCH] Gerber files generation: fix a rounding issue when drawing circles. (explains bug Bug #1339086 ). Gerbview: allows x.7 format (recently indroduced in Gerber format) Also minor coding style fixes. --- common/common_plotGERBER_functions.cpp | 7 ++- gerbview/rs274_read_XY_and_IJ_coordinates.cpp | 44 ++++++++++++------- gerbview/rs274d.cpp | 1 - gerbview/rs274x.cpp | 13 +++--- 4 files changed, 39 insertions(+), 26 deletions(-) diff --git a/common/common_plotGERBER_functions.cpp b/common/common_plotGERBER_functions.cpp index 94a84af4e3..6c5b07bcfb 100644 --- a/common/common_plotGERBER_functions.cpp +++ b/common/common_plotGERBER_functions.cpp @@ -356,14 +356,17 @@ void GERBER_PLOTTER::Arc( const wxPoint& aCenter, double aStAngle, double aEndAn DPOINT devEnd = userToDeviceCoordinates( end ); DPOINT devCenter = userToDeviceCoordinates( aCenter ) - userToDeviceCoordinates( start ); + fprintf( outputFile, "G75*\n" ); // Multiquadrant mode if( aStAngle < aEndAngle ) fprintf( outputFile, "G03" ); else fprintf( outputFile, "G02" ); - fprintf( outputFile, "X%dY%dI%dJ%dD01*\n", int( devEnd.x ), int( devEnd.y ), - int( devCenter.x ), int( devCenter.y ) ); + + fprintf( outputFile, "X%dY%dI%dJ%dD01*\n", + KiROUND( devEnd.x ), KiROUND( devEnd.y ), + KiROUND( devCenter.x ), KiROUND( devCenter.y ) ); fprintf( outputFile, "G74*\nG01*\n" ); // Back to single quadrant and linear interp. } diff --git a/gerbview/rs274_read_XY_and_IJ_coordinates.cpp b/gerbview/rs274_read_XY_and_IJ_coordinates.cpp index f3fa381310..d2b53fd86f 100644 --- a/gerbview/rs274_read_XY_and_IJ_coordinates.cpp +++ b/gerbview/rs274_read_XY_and_IJ_coordinates.cpp @@ -19,25 +19,24 @@ // depending on the gerber file format // this scale list assumes gerber units are imperial. // for metric gerber units, the imperial to metric conversion is made in read functions -static double scale_list[10] = +#define SCALE_LIST_SIZE 10 +static double scale_list[SCALE_LIST_SIZE] = { - 1000.0 * IU_PER_MILS, - 100.0 * IU_PER_MILS, - 10.0 * IU_PER_MILS, - 1.0 * IU_PER_MILS, - 0.1 * IU_PER_MILS, - 0.01 * IU_PER_MILS, - 0.001 * IU_PER_MILS, - 0.0001 * IU_PER_MILS, - 0.00001 * IU_PER_MILS, + 1000.0 * IU_PER_MILS, // x.1 format (certainly useless) + 100.0 * IU_PER_MILS, // x.2 format (certainly useless) + 10.0 * IU_PER_MILS, // x.3 format + 1.0 * IU_PER_MILS, // x.4 format + 0.1 * IU_PER_MILS, // x.5 format + 0.01 * IU_PER_MILS, // x.6 format + 0.0001 * IU_PER_MILS, // x.7 format + 0.00001 * IU_PER_MILS, // provided, but not used 0.000001 * IU_PER_MILS }; - -/** +/* * Function scale - * converts a distance given in floating point to our internal units - * (deci-mils or nano units) + * converts a coordinate given in floating point to Gerbvies internal units + * (currently = 10 nanometers) */ int scaletoIU( double aCoord, bool isMetric ) { @@ -78,6 +77,7 @@ wxPoint GERBER_IMAGE::ReadXYCoord( char*& Text ) Text++; text = line; nbdigits = 0; + while( IsNumber( *Text ) ) { if( *Text == '.' ) // Force decimat format if reading a floating point number @@ -90,6 +90,7 @@ wxPoint GERBER_IMAGE::ReadXYCoord( char*& Text ) } *text = 0; + if( is_float ) { // When X or Y values are float numbers, they are given in mm or inches @@ -101,6 +102,7 @@ wxPoint GERBER_IMAGE::ReadXYCoord( char*& Text ) else { int fmt_scale = (type_coord == 'X') ? m_FmtScale.x : m_FmtScale.y; + if( m_NoTrailingZeros ) { int min_digit = @@ -113,6 +115,7 @@ wxPoint GERBER_IMAGE::ReadXYCoord( char*& Text ) *text = 0; } + current_coord = atoi( line ); double real_scale = scale_list[fmt_scale]; @@ -177,6 +180,7 @@ wxPoint GERBER_IMAGE::ReadIJCoord( char*& Text ) // count digits only (sign and decimal point are not counted) if( (*Text >= '0') && (*Text <='9') ) nbdigits++; + *(text++) = *(Text++); } @@ -193,6 +197,7 @@ wxPoint GERBER_IMAGE::ReadIJCoord( char*& Text ) { int fmt_scale = (type_coord == 'I') ? m_FmtScale.x : m_FmtScale.y; + if( m_NoTrailingZeros ) { int min_digit = @@ -205,20 +210,21 @@ wxPoint GERBER_IMAGE::ReadIJCoord( char*& Text ) *text = 0; } + current_coord = atoi( line ); - if( fmt_scale < 0 || fmt_scale > 9 ) - fmt_scale = 4; // select scale 1.0 - double real_scale = scale_list[fmt_scale]; + if( m_GerbMetric ) real_scale = real_scale / 25.4; + current_coord = KiROUND( current_coord * real_scale ); } if( type_coord == 'I' ) pos.x = current_coord; else if( type_coord == 'J' ) pos.y = current_coord; + continue; } else @@ -246,8 +252,10 @@ int ReadInt( char*& text, bool aSkipSeparator = true ) int ret = (int) strtol( text, &text, 10 ); if( *text == ',' || isspace( *text ) ) + { if( aSkipSeparator ) ++text; + } return ret; } @@ -267,8 +275,10 @@ double ReadDouble( char*& text, bool aSkipSeparator = true ) double ret = strtod( text, &text ); if( *text == ',' || isspace( *text ) ) + { if( aSkipSeparator ) ++text; + } return ret; } diff --git a/gerbview/rs274d.cpp b/gerbview/rs274d.cpp index 74cb464cb9..cb9475d6a1 100644 --- a/gerbview/rs274d.cpp +++ b/gerbview/rs274d.cpp @@ -222,7 +222,6 @@ static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aL aGbrItem->m_Size = aPenSize; aGbrItem->m_Flashed = false; - if( aMultiquadrant ) center = aStart + aRelCenter; else diff --git a/gerbview/rs274x.cpp b/gerbview/rs274x.cpp index aeb7871429..b6ebbf7432 100644 --- a/gerbview/rs274x.cpp +++ b/gerbview/rs274x.cpp @@ -235,15 +235,16 @@ bool GERBER_IMAGE::ExecuteRS274XCommand( int command, if( code == 'X' ) { x_fmt_known = true; - // number of digits after the decimal point (0 to 6 allowed) + // number of digits after the decimal point (0 to 7 allowed) m_FmtScale.x = *text - '0'; m_FmtLen.x = ctmp + m_FmtScale.x; - // m_FmtScale is 0 to 6 + // m_FmtScale is 0 to 7 + // (Old Gerber specification was 0 to 6) if( m_FmtScale.x < 0 ) m_FmtScale.x = 0; - if( m_FmtScale.x > 6 ) - m_FmtScale.x = 6; + if( m_FmtScale.x > 7 ) + m_FmtScale.x = 7; } else { @@ -252,8 +253,8 @@ bool GERBER_IMAGE::ExecuteRS274XCommand( int command, m_FmtLen.y = ctmp + m_FmtScale.y; if( m_FmtScale.y < 0 ) m_FmtScale.y = 0; - if( m_FmtScale.y > 6 ) - m_FmtScale.y = 6; + if( m_FmtScale.y > 7 ) + m_FmtScale.y = 7; } text++; }