Commit 2a801170 authored by charras's avatar charras
Browse files

Commit patch for plot functions from Lorenzo

parent ed71f4b7
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -329,7 +329,7 @@ bool EDA_TextStruct::TextHitTest( EDA_Rect& refArea )
void EDA_TextStruct::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
                           const wxPoint& aOffset, EDA_Colors aColor,
                           int aDrawMode,
                           GRFillMode aFillMode, EDA_Colors aAnchor_color )
                           GRTraceMode aFillMode, EDA_Colors aAnchor_color )
/***************************************************************/

/** Function Draw
@@ -399,7 +399,7 @@ void EDA_TextStruct::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
void EDA_TextStruct::DrawOneLineOfText( WinEDA_DrawPanel* aPanel, wxDC* aDC,
                                        const wxPoint& aOffset, EDA_Colors aColor,
                                        int aDrawMode,
                                        GRFillMode aFillMode, EDA_Colors aAnchor_color,
                                        GRTraceMode aFillMode, EDA_Colors aAnchor_color,
                                        wxString& aText, wxPoint aPos )
{
    int width = m_Width;
+419 −105
Original line number Diff line number Diff line
@@ -14,129 +14,271 @@


/***************************************************************************/
void InitPlotParametresGERBER( wxPoint aOffset, double aXScale, double aYScale )
void Gerber_Plotter::set_viewport( wxPoint offset,
	    double aScale, int orient )
/***************************************************************************/

/** function InitPlotParametresGERBER
/** function set_viewport
  * Set the plot offset for the current plotting
  * @param aOffset = plot offset
  * @param aXScale,aYScale = coordinate scale (scale coefficient for coordinates)
  * @param aScale = coordinate scale (scale coefficient for coordinates)
 */
{
    g_Plot_PlotOrientOptions = 0;
    g_Plot_PlotOffset = aOffset;
    g_Plot_XScale = aXScale;
    g_Plot_YScale = aYScale;
    g_Plot_DefaultPenWidth = 120;            /* epaisseur du trait standard en 1/1000 pouce */
    g_Plot_CurrentPenWidth = -1;
    wxASSERT(!output_file);
    wxASSERT(orient == 0);
    plot_orient_options = 0;
    plot_offset = offset;
    wxASSERT(aScale == 1);
    plot_scale = 1;
    device_scale = 1;
    set_default_line_width(100);            /* epaisseur du trait standard en 1/1000 pouce */
}


/******************************************************************/
void Write_Header_GERBER( const wxString aTitle, FILE* aFile )
/******************************************************************/
/** Function Write_Header_GERBER
void Gerber_Plotter::start_plot( FILE *aFile )
/*****************************************************************/
/** Function start_plot
 * Write GERBER header to file
 * initialize global variable g_Plot_PlotOutputFile
 * @param aTitle: the name of creator (comment)
 * @param aFile: an opened file to write to
 */
{
    char Line[1024];
	g_Plot_PlotOutputFile =  aFile;

    wxASSERT(!output_file);
    final_file = aFile;
    work_file = tmpfile();
    output_file = work_file;
    DateAndTime( Line );
    wxString Title = aTitle + wxT( " " ) + GetBuildVersion();
    fprintf( g_Plot_PlotOutputFile, "G04 (created by %s) date %s*\n", CONV_TO_UTF8( Title ), Line );
    wxString Title = creator + wxT( " " ) + GetBuildVersion();
    fprintf( output_file, "G04 (created by %s) date %s*\n", CONV_TO_UTF8( Title ), Line );

    // Specify linear interpol (G01), unit = INCH (G70), abs format (G90):
    fputs( "G01*\nG70*\nG90*\n", g_Plot_PlotOutputFile );
    fputs( "%MOIN*%\n", g_Plot_PlotOutputFile );     // set unites = INCHES
    fputs( "G01*\nG70*\nG90*\n", output_file );
    fputs( "%MOIN*%\n", output_file );     // set unites = INCHES

    /* Set gerber format to 3.4 */
    fputs( "G04 Gerber Fmt 3.4, Leading zero omitted, Abs format*\n%FSLAX34Y34*%\n",
		g_Plot_PlotOutputFile);
		output_file);

    fputs( "G04 APERTURE LIST*\n", g_Plot_PlotOutputFile );
    fputs( "G04 APERTURE LIST*\n", output_file );
    /* Select the default aperture */
    set_current_line_width(-1);
}

/******************************************************************/
void Gerber_Plotter::end_plot( )
/*****************************************************************/
{
    char     line[1024];
    wxString msg;

/**********************************************/
void LineTo_GERBER( wxPoint aPos, int aCommand )
/**********************************************/
/** Function LineTo_GERBER
  * if aCommand = 'U' initialise the starting point of a line
  * if aCommand = 'D' draw a line from the starting point, or last point to aPos
  * @param aPos = end of the current line.
  * @param aCommand = 'U' or 'D' or 'Z' (Pen up , no moving )
    wxASSERT(output_file);
    /* Outfile is actually a temporary file! */
    fputs( "M02*\n", output_file );
    fflush(output_file);
    rewind( work_file ); // work_file == output_file !!!
    output_file = final_file;


    // Placement des Apertures en RS274X
    while( fgets( line, 1024, work_file ) )
    {
	fputs( line, output_file );
	if( strcmp( strtok( line, "\n\r" ), "G04 APERTURE LIST*" ) == 0 )
	{
	    write_aperture_list();
	    fputs( "G04 APERTURE END LIST*\n", output_file );
	}
    }

    fclose( work_file );
    fclose( final_file );
    output_file = 0;
}

/*************************************************************************************/
void Gerber_Plotter::set_default_line_width( int width )
/*************************************************************************************/

/* Set the default line width (in 1/1000 inch) for the current plotting
 */
{
    default_pen_width = width;      // epaisseur du trait standard en 1/1000 pouce
    current_aperture = apertures.end();
}

/***************************************/
void Gerber_Plotter::set_current_line_width( int width )
/***************************************/

/* Set the Current line width (in 1/1000 inch) for the next plot
 */
{
    int pen_width;

    if( width > 0 )
        pen_width = width;
    else
        pen_width = default_pen_width;

    select_aperture(wxSize(pen_width, pen_width), Aperture::Plotting);
    current_pen_width = pen_width;
}

/******************************************************/
vector<Aperture>::iterator Gerber_Plotter::get_aperture(const wxSize &size,
	Aperture::Aperture_Type type)
/******************************************************/
{
    int last_D_code = 9;
    // Search an existing aperture
    vector<Aperture>::iterator tool = apertures.begin();
    while (tool != apertures.end()) {
	last_D_code = tool->D_code;
	if ((tool->type == type)
		&& (tool->size == size))
	    return tool;
	tool++;
    }
    // Allocate a new aperture
    Aperture new_tool;
    new_tool.size = size;
    new_tool.type = type;
    new_tool.D_code = last_D_code+1;
    apertures.push_back(new_tool);
    return apertures.end()-1;
}

/******************************************************/
void Gerber_Plotter::select_aperture(const wxSize &size, Aperture::Aperture_Type type)
/******************************************************/
{
    wxASSERT(output_file);
    if ((current_aperture == apertures.end())
	    || (current_aperture->type != type)
	    || (current_aperture->size != size)) {
	/* Pick an existing aperture or create a new one */
	current_aperture = get_aperture(size, type);
	fprintf( output_file, "G54D%d*\n", current_aperture->D_code );
    }
}

/******************************************************/
void Gerber_Plotter::write_aperture_list( )
/******************************************************/
/* Genere la liste courante des D_CODES
 * Retourne le nombre de D_Codes utilises
 * Genere une sequence RS274X
 */
{
	static wxPoint LastPoint;
    switch ( aCommand )
    wxASSERT(output_file);
    char cbuf[1024];

    /* Init : */
    for (vector<Aperture>::iterator tool=apertures.begin();
	    tool != apertures.end(); tool++)
    {
	const float fscale = 0.0001f * plot_scale; // For 3.4 format
	char* text;

	text = cbuf + sprintf( cbuf, "%%ADD%d", tool->D_code);

	switch( tool->type )
	{
	case Aperture::Circle:
	    sprintf( text, "C,%f*%%\n", tool->size.x * fscale );
	    break;

	case Aperture::Rect:
	    sprintf( text, "R,%fX%f*%%\n", tool->size.x * fscale,
		    tool->size.y * fscale );
	    break;

	case Aperture::Plotting:
	    sprintf( text, "C,%f*%%\n", tool->size.x * fscale );
	    break;

	case Aperture::Oval:
	    sprintf( text, "O,%fX%f*%%\n", tool->size.x * fscale,
		    tool->size.y * fscale );
	    break;
	}

	fputs( cbuf, output_file );
    }
}

/**********************************************/
void Gerber_Plotter::pen_to( wxPoint aPos, char plume )
{
    wxASSERT(output_file);
    user_to_device_coordinates( aPos );

    switch ( plume )
	{
		case 'Z':
			return;
	break;

		case 'U':
	fprintf( output_file, "X%5.5dY%5.5dD02*\n", aPos.x, aPos.y );
			break;

		case 'D':
            PlotGERBERLine( LastPoint, aPos, g_Plot_CurrentPenWidth );
	fprintf( output_file, "X%5.5dY%5.5dD01*\n", aPos.x, aPos.y );
	}
	LastPoint = aPos;
    pen_state = plume;
}

/** Function PlotGERBERLine
 * Plot a line
 * the D_CODE **MUST** have already selected (this is just the line plot)
 * @param aStartPos = starting point of the line
 * @param aEndPos   = ending point of the line
 * @param aThickness = line thickness (not used here)
*/
void PlotGERBERLine( wxPoint aStartPos, wxPoint aEndPos, int aThickness )
/************************************************************/
void Gerber_Plotter::rect( wxPoint p1, wxPoint p2, FILL_T fill, int width )
/************************************************************/
{
    UserToDeviceCoordinate( aStartPos );
    UserToDeviceCoordinate( aEndPos );
    fprintf( g_Plot_PlotOutputFile, "X%5.5dY%5.5dD02*\n", aStartPos.x, aStartPos.y );
    fprintf( g_Plot_PlotOutputFile, "X%5.5dY%5.5dD01*\n", aEndPos.x, aEndPos.y );
    wxASSERT(output_file);
    int coord[10] = {
	p1.x, p1.y,
	p1.x, p2.y,
	p2.x, p2.y,
	p2.x, p1.y,
	p1.x, p1.y
    };
    poly( 5, coord, fill, width);
}


/********************************************************************/
void PlotCircle_GERBER( wxPoint aCentre, int aRadius, int aWidth )
void Gerber_Plotter::circle( wxPoint pos, int diametre, FILL_T fill, int width )
/********************************************************************/
/** Function PlotCircle_GERBER
 * writes a non filled circle to output file
 * Plot one circle as segments (6 to 16 depending on its radius
 * @param aCentre = centre coordintes
 * @param aRadius = radius of the circle
 * @param aWidth = line width (noc currently used, D_CODEs must be selected before)
 * @param aWidth = line width
*/
{
    int ii;
    wxASSERT(output_file);
    wxPoint start,end;
    int delta;      	/* increment (in 0.1 degrees) to draw circles */
    double aRadius = diametre / 2;
    const int delta = 3600/32; 	/* increment (in 0.1 degrees) to draw circles */

    delta = 3600/32;    /* there are delta segments for draw a circle */

    start.x = aCentre.x + aRadius;
    start.y = aCentre.y;
    for( ii = delta; ii < 3600; ii += delta )
    start.x = pos.x + aRadius;
    start.y = pos.y;
    set_current_line_width(width);
    move_to(start);
    for(int ii = delta; ii < 3600; ii += delta )
    {
        end.x = aCentre.x + (int) (aRadius * fcosinus[ii]);
        end.y = aCentre.y + (int) (aRadius * fsinus[ii]);
        PlotGERBERLine( start, end, aWidth );
        start = end;
        end.x = pos.x + (int) (aRadius * fcosinus[ii]);
        end.y = pos.y + (int) (aRadius * fsinus[ii]);
        line_to(end);
    }

    end.x = aCentre.x + aRadius;
    end.y = aCentre.y;
	PlotGERBERLine( start, end, aWidth );
    finish_to( start );
}


/***************************************************************/
void PlotFilledPolygon_GERBER( int aCornersCount, int* aCoord )
void Gerber_Plotter::poly( int nb_segm, int* coord, FILL_T fill, int width )
/***************************************************************/
/** Function PlotFilledPolygon_GERBER
 * writes a filled polyline to output file
@@ -144,59 +286,231 @@ void PlotFilledPolygon_GERBER( int aCornersCount, int* aCoord )
 * @param aCoord = buffer of corners coordinates
*/
{
    int     ii;
    wxASSERT(output_file);
    wxPoint pos, startpos;
    set_current_line_width(width);

    fputs( "G36*\n", g_Plot_PlotOutputFile );
    pos.x = *aCoord;
    aCoord++;
    pos.y = *aCoord;
    aCoord++;
    UserToDeviceCoordinate( pos );
    startpos = pos;
    fprintf( g_Plot_PlotOutputFile, "X%5.5dY%5.5dD02*\n", pos.x, pos.y );
    for( ii = 1; ii < aCornersCount; ii++ )
    if (fill)
	fputs( "G36*\n", output_file );
    startpos.x = *coord++;
    startpos.y = *coord++;
    move_to(startpos);
    for(int ii = 1; ii < nb_segm; ii++ )
    {
        pos.x = *coord++;
        pos.y = *coord++;
	line_to( pos );
    }
    if (fill)
    {
        pos.x = *aCoord;
        aCoord++;
        pos.y = *aCoord;
        aCoord++;
        UserToDeviceCoordinate( pos );
        fprintf( g_Plot_PlotOutputFile, "X%5.5dY%5.5dD01*\n", pos.x, pos.y );
	finish_to(startpos);
	fputs( "G37*\n", output_file );
    }
    else
    {
	pen_finish();
    }
}

    fprintf( g_Plot_PlotOutputFile, "X%5.5dY%5.5dD01*\n", startpos.x, startpos.y );
    fputs( "G37*\n", g_Plot_PlotOutputFile );
void Gerber_Plotter::flash_pad_circle(wxPoint pos, int diametre,
	    GRTraceMode trace_mode)
/* Plot a circular pad or via at the user position pos
 */
{
    wxASSERT(output_file);
    wxSize  size( diametre, diametre );

    switch (trace_mode)
    {
    case FILAIRE:
    case SKETCH:
	set_current_line_width(-1);
	circle(pos, diametre-current_pen_width, NO_FILL);
	break;
    case FILLED:
	user_to_device_coordinates( pos );
	select_aperture(size, Aperture::Circle);
	fprintf( output_file, "X%5.5dY%5.5dD03*\n", pos.x, pos.y );
	break;
    }
}

void Gerber_Plotter::flash_pad_oval(wxPoint pos, wxSize size, int orient,
	    GRTraceMode trace_mode)
/* Trace 1 pastille PAD_OVAL en position pos_X,Y:
 *     dimensions dx, dy,
 *     orientation orient
 * Pour une orientation verticale ou horizontale, la forme est flashee
 * Pour une orientation quelconque la forme est tracee comme un segment
 */
{
    wxASSERT(output_file);
    int     x0, y0, x1, y1, delta;

/*******************************************************************/
void PlotPolygon_GERBER( int aCornersCount, int* aCoord, int aWidth )
/*******************************************************************/
/** Function PlotPolygon_GERBER
 * writes a closed polyline (not a filled polygon) to output file
 * @param aCornersCount = numer of corners
 * @param aCoord = buffer of corners coordinates
 * @param aWidth = line width (not currently used, D_CODEs must be selected before)
    /* Trace de la forme flashee */
    if(( orient == 0 || orient == 900 || orient == 1800 || orient == 2700 )
	    && trace_mode == FILLED)
    {
	if( orient == 900 || orient == 2700 )  /* orient tournee de 90 deg */
	    EXCHG( size.x, size.y );
	user_to_device_coordinates( pos );
	select_aperture(size, Aperture::Oval);
	fprintf( output_file, "X%5.5dY%5.5dD03*\n", pos.x, pos.y );
    }
    else /* Forme tracee comme un segment */
    {
	if( size.x > size.y )
	{
	    EXCHG( size.x, size.y );
	    if( orient < 2700 )
		orient += 900;
	    else
		orient -= 2700;
	}
	if (trace_mode == FILLED)
	{
	    /* la pastille est ramenee a une pastille ovale avec dy > dx */
	    delta = size.y - size.x;
	    x0    = 0;
	    y0    = -delta / 2;
	    x1    = 0;
	    y1    = delta / 2;
	    RotatePoint( &x0, &y0, orient );
	    RotatePoint( &x1, &y1, orient );
	    thick_segment( wxPoint( pos.x + x0, pos.y + y0 ),
		    wxPoint( pos.x + x1, pos.y + y1 ),
		    size.x, trace_mode );
	} else
	    sketch_oval(pos, size, orient, -1);
    }
}

void Gerber_Plotter::flash_pad_rect(wxPoint pos, wxSize size,
	    int orient, GRTraceMode trace_mode)
/* Plot 1 rectangular pad
 * donne par son centre, ses dimensions, et son orientation
 * For a vertical or horizontal shape, the shape is an aperture (Dcode) and it is flashed
 * For others orientations the shape is plotted as a polygon
 */
{
    wxPoint start, end, startpoint;
    startpoint.x = *aCoord++;
    startpoint.y = *aCoord++;
    start = startpoint;
    for( int ii = 0; ii < aCornersCount-1; ii++ )
    wxASSERT(output_file);
    /* Trace de la forme flashee */
    switch( orient )
    {
        end.x = *aCoord;
        aCoord++;
        end.y = *aCoord;
        aCoord++;
        PlotGERBERLine(start, end, aWidth );
        start = end;
    case 900:
    case 2700: /* la rotation de 90 ou 270 degres revient a permutter des dimensions */
        EXCHG( size.x, size.y );

    // Pass through

    case 0:
    case 1800:
	switch (trace_mode) {
	case FILAIRE:
	case SKETCH:
	    set_current_line_width(-1);
	    rect(wxPoint(pos.x-(size.x-current_pen_width)/2,
			pos.y-(size.y-current_pen_width)/2),
		    wxPoint(pos.x+(size.x-current_pen_width)/2,
			pos.y+(size.y-current_pen_width)/2),
		    NO_FILL);
	    break;
	case FILLED:
	    user_to_device_coordinates( pos );
	    select_aperture(size, Aperture::Rect);
	    fprintf( output_file, "X%5.5dY%5.5dD03*\n", pos.x, pos.y );
	    break;
	}
	break;

    if ( startpoint != end )    // Close poly
        PlotGERBERLine(end, startpoint, aWidth );
    default: /* plot pad shape as polygon */
        flash_pad_trapez( pos, size, wxSize( 0, 0 ), orient, trace_mode );
        break;
    }
}

void Gerber_Plotter::flash_pad_trapez(wxPoint pos, wxSize size, wxSize delta,
	    int orient, GRTraceMode trace_mode)
/* Trace 1 pad trapezoidal donne par :
 *    son centre pos.x,pos.y
 *    ses dimensions size.x et size.y
 *    les variations delta.x et delta.y ( 1 des deux au moins doit etre nulle)
 *    son orientation orient en 0.1 degres
 *    le mode de trace (FILLED, SKETCH, FILAIRE)
 *
 * Le trace n'est fait que pour un trapeze, c.a.d que delta.x ou delta.y
 *    = 0.
 *
 *   les notation des sommets sont ( vis a vis de la table tracante )
 *
 * "       0 ------------- 3   "
 * "        .             .    "
 * "         .     O     .     "
 * "          .         .      "
 * "           1 ---- 2        "
 *
 *
 *   exemple de Disposition pour delta.y > 0, delta.x = 0
 * "           1 ---- 2        "
 * "          .         .      "
 * "         .     O     .     "
 * "        .             .    "
 * "       0 ------------- 3   "
 *
 *
 *   exemple de Disposition pour delta.y = 0, delta.x > 0
 * "       0                  "
 * "       . .                "
 * "       .     .            "
 * "       .           3      "
 * "       .           .      "
 * "       .     O     .      "
 * "       .           .      "
 * "       .           2      "
 * "       .     .            "
 * "       . .                "
 * "       1                  "
 */
{
    wxASSERT(output_file);
    int     ii, jj;
    int     dx, dy;
    wxPoint polygon[4]; /* polygon corners */
    int     coord[10];
    int     ddx, ddy;

    /* calcul des dimensions optimales du spot choisi = 1/4 plus petite dim */
    dx = size.x - abs( delta.y );
    dy = size.y - abs( delta.x );

    dx  = size.x / 2;
    dy  = size.y / 2;
    ddx = delta.x / 2;
    ddy = delta.y / 2;

    polygon[0].x = -dx - ddy;
    polygon[0].y = +dy + ddx;
    polygon[1].x = -dx + ddy;
    polygon[1].y = -dy - ddx;
    polygon[2].x = +dx - ddy;
    polygon[2].y = -dy + ddx;
    polygon[3].x = +dx + ddy;
    polygon[3].y = +dy - ddx;

    /* Dessin du polygone et Remplissage eventuel de l'interieur */

    for( ii = 0, jj = 0; ii < 4; ii++ )
    {
	RotatePoint( &polygon[ii].x, &polygon[ii].y, orient );
	coord[jj] = polygon[ii].x += pos.x;
	jj++;
	coord[jj] = polygon[ii].y += pos.y;
	jj++;
    }
    coord[8]=coord[0];
    coord[9]=coord[1];

    set_current_line_width(-1);
    poly( 5, coord, trace_mode==FILLED?FILLED_SHAPE:NO_FILL );
}
+426 −118

File changed.

Preview size limit exceeded, changes collapsed.

+307 −179

File changed.

Preview size limit exceeded, changes collapsed.

+418 −151

File changed.

Preview size limit exceeded, changes collapsed.

Loading