Commit 3e477651 authored by charras's avatar charras
Browse files

finishing work on hpgl plotting functions

parent f9642fd4
Loading
Loading
Loading
Loading
+86 −78
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ eda_global bool PlotPadsOnSilkLayer /* Plot pads sur couche serigraphie */
#endif
;
eda_global bool Plot_Pads_All_Layers;   /* Plot pads meme n'appartenant pas a la
                                        couche ( utile pour serigraphie) */
                                          * couche ( utile pour serigraphie) */

/* Variables utiles */

@@ -91,7 +91,7 @@ eda_global float Scale_X, Scale_Y ; /* coeff d'agrandissement en X et Y demande
eda_global wxPoint g_PlotOffset;        /* Offset de trace modifies par l'echelle */

eda_global int     g_PlotLine_Width; /* Largeur du trait en mode filaire (utilise en serigraphie,
                                    pour traces en mode sketch et filaire) */
                                   * pour traces en mode sketch et filaire) */

eda_global int     g_PlotFormat /* id for plot format (see enum PlotFormat in plot_common.h) */
#ifdef MAIN
@@ -99,9 +99,9 @@ eda_global int g_PlotFormat /* id for plot format (see enum PlotFormat in plot_
#endif
;
eda_global int g_PlotOrient;  /* numero de code de l'orientation du trace ( voir
                            defines precedents):
                            0 = normal
                            PLOT_MIROIR = MIROIR
                                * defines precedents):
                                * 0 = normal
                                * PLOT_MIROIR = MIROIR
                               */
eda_global int g_PlotScaleOpt       // 0 = automatique, >=1 echelle specifiee
#ifdef MAIN
@@ -129,8 +129,9 @@ eda_global int g_DrillShapeOpt

/* PLOT_RTN.CC */
void    PlotTextePcb( TEXTE_PCB* pt_texte, int format_plot, int masque_layer );

/* Trace 1 Texte type PCB , c.a.d autre que les textes sur modules,
        prepare les parametres de trace de texte */
  * prepare les parametres de trace de texte */
void    PlotArc( int format_plot, wxPoint centre, int start_angle, int end_angle,
                 int rayon, int width );
void    PlotCircle( int format_plot, int width, wxPoint centre, int rayon );
@@ -151,13 +152,21 @@ void PlotFilledAreas( ZONE_CONTAINER * aZone, int aFormat);
void    SelectD_CODE_For_LineDraw( int aSize );
void    trace_1_contour_GERBER( wxPoint pos, wxSize size, wxSize delta,
                                int penwidth, int orient );

/* Trace 1 contour rectangulaire ou trapezoidal d'orientation quelconque
         donne par son centre, ses dimensions,
         ses variations, l'epaisseur du trait et son orientation orient */
  *  donne par son centre, ses dimensions,
  *  ses variations, l'epaisseur du trait et son orientation orient */

/* PLOTHPGL.CC */
void trace_1_segment_HPGL(int pos_X0,int pos_Y0,int pos_X1,int pos_Y1,
                            int hauteur);
/* PLOTHPGL.CPP */

/** Function Plot a filled segment (track)
 * @param aStart = starting point
 * @param aEnd = ending point
 * @param aWidth = segment width (thickness)
 * @param aPlotMode = FILLED, SKETCH ..
 * @return true if Ok, false if aWidth > pen size (the segment is always plotted)
 */
bool    Plot_Filled_Segment_HPGL( wxPoint aStart, wxPoint aEnd, int aWidth, GRFillMode aPlotMode );

void    trace_1_pad_TRAPEZE_HPGL( wxPoint padpos, wxSize size, wxSize delta,
                                  int orient, int modetrace );
@@ -180,4 +189,3 @@ void trace_1_pad_TRAPEZE_POST(wxPoint centre, wxSize size, wxSize delta,


#endif  /* #define PCBPLOT_H */
+136 −95
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ void WinEDA_BasePcbFrame::Plot_Serigraphie( int format_plot,
                        trace_1_pastille_RONDE_POST( pos, size.x, FILAIRE );
                        break;
                    }

                    break;

                case PAD_OVAL:
@@ -129,6 +130,7 @@ void WinEDA_BasePcbFrame::Plot_Serigraphie( int format_plot,
                                                     pt_pad->m_Orient, FILAIRE );
                        break;
                    }

                    break;

                case PAD_TRAPEZOID:
@@ -156,6 +158,7 @@ void WinEDA_BasePcbFrame::Plot_Serigraphie( int format_plot,
                                                  FILAIRE );
                        break;
                    }

                    break;
                }

@@ -179,6 +182,7 @@ void WinEDA_BasePcbFrame::Plot_Serigraphie( int format_plot,
                                                        (int) pt_pad->m_Orient, FILAIRE );
                        break;
                    }

                    break;
                }
            }
@@ -260,7 +264,8 @@ void WinEDA_BasePcbFrame::Plot_Serigraphie( int format_plot,
                wxString errMsg;

                errMsg.Printf(
                  _("Your BOARD has a bad layer number of %u for module\n %s's \"module text\" text of %s."),
                    _(
                        "Your BOARD has a bad layer number of %u for module\n %s's \"module text\" text of %s." ),
                    textLayer, Module->GetReference().GetData(), pt_texte->m_Text.GetData() );
                DisplayError( this, errMsg );
                goto exit;
@@ -492,7 +497,7 @@ void Plot_1_EdgeModule( int format_plot, EDGE_MODULE* PtEdge )
            break;

        case PLOT_FORMAT_HPGL:
            trace_1_segment_HPGL( pos.x, pos.y, end.x, end.y, thickness );
            Plot_Filled_Segment_HPGL( pos, end, thickness, (GRFillMode)g_Plot_Mode );
            break;

        case PLOT_FORMAT_POST:
@@ -604,6 +609,7 @@ void PlotTextePcb( TEXTE_PCB* pt_texte, int format_plot, int masque_layer )
/*********************************************************/
void PlotFilledAreas( ZONE_CONTAINER* aZone, int aFormat )
/*********************************************************/

/* Plot areas (given by .m_FilledPolysList member) in a zone
 */
{
@@ -615,6 +621,8 @@ void PlotFilledAreas( ZONE_CONTAINER * aZone, int aFormat )
        return;

    // We need a buffer to store corners coordinates:

    imax++;   // provide room to sore an extra coordinte to close the ploygon
    if( CornersBuffer == NULL )
    {
        CornersBufferSize = imax * 4;
@@ -627,6 +635,8 @@ void PlotFilledAreas( ZONE_CONTAINER * aZone, int aFormat )
        CornersBuffer = (int*) realloc( CornersBuffer, CornersBufferSize * sizeof(int) );
    }

    imax--;

    // Plot all filled areas
    int corners_count = 0;
    for( unsigned ic = 0, ii = 0; ic < imax; ic++ )
@@ -635,8 +645,18 @@ void PlotFilledAreas( ZONE_CONTAINER * aZone, int aFormat )
        CornersBuffer[ii++] = corner->x;
        CornersBuffer[ii++] = corner->y;
        corners_count++;
        if( corner->end_contour )
        {   // Plot the current filled area
        if( corner->end_contour )   // Plot the current filled area outline
        {
            // First, close the outline
            if( CornersBuffer[0] != CornersBuffer[ii - 2] || CornersBuffer[1] !=
                CornersBuffer[ii - 1] )
            {
                CornersBuffer[ii++] = CornersBuffer[0];
                CornersBuffer[ii]   = CornersBuffer[1];
                corners_count++;
            }

            // Plot the current filled area outline
            if( aZone->m_FillMode == 0 )  // We are using solid polygons (if != 0: using segments in m_Zone)
                PlotFilledPolygon( aFormat, corners_count, CornersBuffer );
            if( aZone->m_ZoneMinThickness > 0 )
@@ -647,6 +667,7 @@ void PlotFilledAreas( ZONE_CONTAINER * aZone, int aFormat )
    }
}


/******************************************************************************/
void PlotDrawSegment( DRAWSEGMENT* pt_segm, int Format, int masque_layer )
/******************************************************************************/
@@ -702,7 +723,7 @@ void PlotDrawSegment( DRAWSEGMENT* pt_segm, int Format, int masque_layer )
        else if( pt_segm->m_Shape == S_ARC )
            PlotArc( PLOT_FORMAT_HPGL, start, StAngle, EndAngle, radius, thickness );
        else
            trace_1_segment_HPGL( start.x, start.y, end.x, end.y, thickness );
            Plot_Filled_Segment_HPGL( start, end, thickness, (GRFillMode)g_Plot_Mode );
        break;

    case PLOT_FORMAT_POST:
@@ -762,10 +783,13 @@ void PlotFilledPolygon( int format_plot, int nbpoints, int* coord )
    }
}


/**********************************************************************/
void PlotPolygon( int format_plot, int nbpoints, int* coord, int width )
/**********************************************************************/
/* plot a polygon */

/* plot a non filled polygon
 */
{
    switch( format_plot )
    {
@@ -775,7 +799,28 @@ void PlotPolygon( int format_plot, int nbpoints, int* coord, int width )
        break;

    case PLOT_FORMAT_HPGL:
        PlotPolyHPGL( nbpoints, coord, false, width );
    {
        // Compute pen_dim (from g_HPGL_Pen_Diam in mils) in pcb units,
        // with plot scale (if Scale is 2, pen diametre is always g_HPGL_Pen_Diam
        // so apparent pen diam is real pen diam / Scale
        int      pen_diam = (int) round( (g_HPGL_Pen_Diam * U_PCB) / Scale_X ); // Assume Scale_X # Scale_Y
        wxString msg;
        if( pen_diam >= width )
            PlotPolyHPGL( nbpoints, coord, false, width ); // PlotPolyHPGL does not handle width
        else
        {
            wxPoint start, end;
            start.x = *coord++;
            start.y = *coord++;
            for( int ii = 1; ii < nbpoints; ii++ )
            {
                end.x = *coord++;
                end.y = *coord++; 
                Plot_Filled_Segment_HPGL( start, end, width, (GRFillMode)g_Plot_Mode );
                start = end;
            }
        }
    }
        break;

    case PLOT_FORMAT_POST:
@@ -845,11 +890,9 @@ void PlotArc( int format_plot, wxPoint centre, int start_angle, int end_angle,
            break;

        case PLOT_FORMAT_HPGL:
            trace_1_segment_HPGL( centre.x + ox,
                                  centre.y + oy,
                                  centre.x + fx,
                                  centre.y + fy,
                                  thickness );
            Plot_Filled_Segment_HPGL( wxPoint(centre.x + ox, centre.y + oy),
                                      wxPoint(centre.x + fx, centre.y + fy),
                                         thickness,  (GRFillMode)g_Plot_Mode );
            break;

        case PLOT_FORMAT_POST:
@@ -873,11 +916,9 @@ void PlotArc( int format_plot, wxPoint centre, int start_angle, int end_angle,
        break;

    case PLOT_FORMAT_HPGL:
        trace_1_segment_HPGL( centre.x + ox,
                              centre.y + oy,
                              centre.x + fx,
                              centre.y + fy,
                              thickness );
            Plot_Filled_Segment_HPGL( wxPoint(centre.x + ox, centre.y + oy),
                                      wxPoint(centre.x + fx, centre.y + fy),
                                         thickness,  (GRFillMode)g_Plot_Mode );
        break;

    case PLOT_FORMAT_POST:
+77 −185
Original line number Diff line number Diff line
@@ -346,78 +346,86 @@ void WinEDA_BasePcbFrame::Plot_Layer_HPGL( FILE* File, int masque_layer,
        if( pts->Type() == TYPE_VIA )
            continue;

        if( (g_TabOneLayerMask[pts->GetLayer()] & masque_layer) == 0 )
            continue;

        size.x = size.y = pts->m_Width;
        start  = pts->m_Start;
        end    = pts->m_End;

        if( size.x > pen_diam ) /* c.a.d si largeur piste > diam plume */
            trace_1_pastille_RONDE_HPGL( start, size.x, modetrace );

        /* Trace d'un segment de piste */
        trace_1_segment_HPGL( start.x, start.y, end.x, end.y, size.x );
        /* Complement de Trace en mode Remplissage */
        if( (g_Plot_Mode == FILLED) && (pen_diam <= size.x ) )
        {
            while( ( size.x -= (int) ( (pen_rayon - pen_recouvrement) * 2 ) ) > 0 )
            {
                trace_1_segment_HPGL( start.x, start.y, end.x, end.y,
                                     MAX( size.x, pen_diam ) );
            }
        }

        if( size.x > pen_diam )
            trace_1_pastille_RONDE_HPGL( end, size.x, modetrace );
        if( (g_TabOneLayerMask[pts->GetLayer()] & masque_layer) )
            Plot_Filled_Segment_HPGL( pts->m_Start, pts->m_End, pts->m_Width, (GRFillMode)g_Plot_Mode );
    }

    /* trace des segments pistes et zones */
    for( pts = m_Pcb->m_Zone; pts != NULL; pts = pts->Next() )
    {
        if( g_TabOneLayerMask[pts->GetLayer()] & masque_layer )
        if( (g_TabOneLayerMask[pts->GetLayer()] & masque_layer) )
            Plot_Filled_Segment_HPGL( pts->m_Start, pts->m_End, pts->m_Width, (GRFillMode)g_Plot_Mode );
    }

    /* Plot filled ares */
    for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ )
    {
            size.x = size.y = pts->m_Width;
            start  = pts->m_Start;
            end    = pts->m_End;
        ZONE_CONTAINER* zone = m_Pcb->GetArea( ii );
        if( ( ( 1 << zone->GetLayer() ) & masque_layer ) == 0 )
            continue;
        PlotFilledAreas( zone, PLOT_FORMAT_HPGL );
    }
}

            if( size.x > pen_diam ) /* c.a.d si largeur piste > diam plume */
                trace_1_pastille_RONDE_HPGL( start, size.x, modetrace );

            /* Trace d'un segment de piste */
            trace_1_segment_HPGL( start.x, start.y, end.x, end.y, size.x );
            /* Complement de Trace en mode Remplissage */
            if( (g_Plot_Mode == FILLED) && (pen_diam <= size.x ) )
/*********************************************************************************************/
bool Plot_Filled_Segment_HPGL( wxPoint aStart, wxPoint aEnd, int aWidth, GRFillMode aPlotMode )
/*********************************************************************************************/

/** Function Plot a filled segment (track)
 * @param aStart = starting point
 * @param aEnd = ending point
 * @param aWidth = segment width (thickness)
 * @param aPlotMode = FILLED, SKETCH ..
 * @return true if Ok, false if aWidth > pen size (the segment is always plotted)
 */
{
                while( ( size.x -= (int) ( (pen_rayon - pen_recouvrement) * 2 ) ) > 0 )
    wxPoint center;
    wxSize  size;
    int     orient;

    if( (pen_diam >= aWidth) || (g_Plot_Mode == FILAIRE) )  /* just a line is Ok */
    {
                    trace_1_segment_HPGL( start.x, start.y, end.x, end.y,
                                         MAX( size.x, pen_diam ) );
                }
        Move_Plume_HPGL( aStart, 'U' );
        Move_Plume_HPGL( aEnd, 'D' );
        Plume_HPGL( 'U' );
        return pen_diam <= aWidth;;
    }

            if( size.x > pen_diam )
                trace_1_pastille_RONDE_HPGL( end, size.x, modetrace );
        }
    }
    // A segment is like an oval pal, so use trace_1_pastille_OVALE_HPGL to do the work.
    center.x = (aStart.x + aEnd.x) / 2;
    center.y = (aStart.y + aEnd.y) / 2;

    size.x = aEnd.x - aStart.x;
    size.y = aEnd.y - aStart.y;
    if ( size.y == 0 )
        orient = 0;
    else if ( size.x == 0 )
        orient = 900;
    else orient = - (int) (atan2( (double)size.y, (double)size.x ) * 1800.0 / M_PI);
    size.x = (int) sqrt( ((double)size.x * size.x) + ((double)size.y * size.y) ) + aWidth;   // module.
    size.y = aWidth;

    trace_1_pastille_OVALE_HPGL( center, size, orient, aPlotMode );

    return pen_diam <= aWidth;
}


/************************************************************************************/
void trace_1_pastille_OVALE_HPGL( wxPoint pos, wxSize size, int orient, int modetrace )
void trace_1_pastille_OVALE_HPGL( wxPoint pos, wxSize size, int aOrient, int modetrace )
/************************************************************************************/
/* Trace 1 pastille PAD_OVAL en position pos_X,Y , de dim size.x, size.y */
{
    int rayon, deltaxy, cx, cy;
    int trace_orient = orient;

    /* la pastille est ramenee a une pastille ovale avec size.y > size.x
     *  ( ovale vertical en orientation 0 ) */
    if( size.x > size.y )
    {
        EXCHG( size.x, size.y ); trace_orient += 900;
        if( orient >= 3600 )
            trace_orient -= 3600;
        EXCHG( size.x, size.y ); aOrient += 900;
        if( aOrient >= 3600 )
            aOrient -= 3600;
    }
    deltaxy = size.y - size.x; /* = distance entre centres de l'ovale */
    rayon   = size.x / 2;
@@ -425,41 +433,41 @@ void trace_1_pastille_OVALE_HPGL( wxPoint pos, wxSize size, int orient, int mode
    if( modetrace == FILLED )
    {
        PlotRectangularPad_HPGL( pos, wxSize( size.x, deltaxy ),
                                 orient, modetrace );
                                 aOrient, modetrace );
        cx = 0; cy = deltaxy / 2;
        RotatePoint( &cx, &cy, trace_orient );
        RotatePoint( &cx, &cy, aOrient );
        trace_1_pastille_RONDE_HPGL( wxPoint( cx + pos.x, cy + pos.y ), size.x, modetrace );
        Plume_HPGL( 'U' );
        cx = 0; cy = -deltaxy / 2;
        RotatePoint( &cx, &cy, trace_orient );
        RotatePoint( &cx, &cy, aOrient );
        trace_1_pastille_RONDE_HPGL( wxPoint( cx + pos.x, cy + pos.y ), size.x, modetrace );
    }
    else    /* Trace en mode FILAIRE */
    else    /* Trace en mode SKETCH */
    {
        cx = -rayon; cy = -deltaxy / 2;
        RotatePoint( &cx, &cy, trace_orient );
        RotatePoint( &cx, &cy, aOrient );
        Move_Plume_HPGL( wxPoint( cx + pos.x, cy + pos.y ), 'U' );
        cx = -rayon; cy = deltaxy / 2;
        RotatePoint( &cx, &cy, trace_orient );
        RotatePoint( &cx, &cy, aOrient );
        Move_Plume_HPGL( wxPoint( cx + pos.x, cy + pos.y ), 'D' );

        cx = rayon; cy = -deltaxy / 2;
        RotatePoint( &cx, &cy, trace_orient );
        RotatePoint( &cx, &cy, aOrient );
        Move_Plume_HPGL( wxPoint( cx + pos.x, cy + pos.y ), 'U' );
        cx = rayon; cy = deltaxy / 2;
        RotatePoint( &cx, &cy, trace_orient );
        RotatePoint( &cx, &cy, aOrient );
        Move_Plume_HPGL( wxPoint( cx + pos.x, cy + pos.y ), 'D' );
        Plume_HPGL( 'U' );

        cx = 0; cy = -deltaxy / 2;
        RotatePoint( &cx, &cy, trace_orient );
        cx = 0; cy = deltaxy / 2;
        RotatePoint( &cx, &cy, aOrient );
        PlotArc( PLOT_FORMAT_HPGL, wxPoint( cx + pos.x, cy + pos.y ),
                 trace_orient, trace_orient + 1800,
                 -aOrient, -aOrient - 1800,
                 size.x / 2, pen_diam );
        cx = 0; cy = deltaxy / 2;
        RotatePoint( &cx, &cy, trace_orient );
        cx = 0; cy = -deltaxy / 2;
        RotatePoint( &cx, &cy, aOrient );
        PlotArc( PLOT_FORMAT_HPGL, wxPoint( cx + pos.x, cy + pos.y ),
                 trace_orient + 1800, trace_orient,
                 -aOrient - 1800, -aOrient,
                 size.x / 2, pen_diam );
    }

@@ -761,119 +769,3 @@ void trace_1_pad_TRAPEZE_HPGL( wxPoint padpos, wxSize size, wxSize delta,

    Plume_HPGL( 'U' );
}


/********************************************************************/
void trace_1_segment_HPGL( int pos_X0, int pos_Y0, int pos_X1, int pos_Y1,
                           int epaisseur )
/********************************************************************/

/* Trace 1 rectangle donne par son axe et son epaisseur (piste rectangulaire)
 *  en mode SKETCH
 */
{
    float  alpha;   /* angle de l'axe du rectangle */
    wxSize size;    /* coord relatives a l'origine du segment de sa fin */
    int    dh;      /* demi epaisseur du segment compte tenu de la
                     *  largeur de la plume */
    int    dx_rot;  /* coord du segment en repere modifie ( size.y_rot etant nul )*/
    float  sin_alpha, cos_alpha;

    size.x = pos_X1 - pos_X0; size.y = pos_Y1 - pos_Y0;
    dh = (epaisseur - (int) pen_diam ) / 2;
    if( dh < 0 )
    {
        dh = 0; s_Nb_Plot_Errors++;
    }

    if( (dh == 0) || (g_Plot_Mode == FILAIRE) )  /* Le trace se reduit a 1 trait */
    {
        Move_Plume_HPGL( wxPoint( pos_X0, pos_Y0 ), 'U' );
        Move_Plume_HPGL( wxPoint( pos_X1, pos_Y1 ), 'D' );
        Plume_HPGL( 'U' );
        return;
    }

    if( size.x < 0 )
    {
        EXCHG( pos_X0, pos_X1 );  EXCHG( pos_Y0, pos_Y1 );
        size.y = -size.y; size.x = -size.x;
    }

    if( size.y == 0 )  /* segment horizontal */
    {
        Move_Plume_HPGL( wxPoint( pos_X0, pos_Y0 - dh ), 'U' );
        Move_Plume_HPGL( wxPoint( pos_X1, pos_Y1 - dh ), 'D' );
        Move_Plume_HPGL( wxPoint( pos_X1, pos_Y1 + dh ), 'D' );
        Move_Plume_HPGL( wxPoint( pos_X0, pos_Y0 + dh ), 'D' );
        Move_Plume_HPGL( wxPoint( pos_X0, pos_Y0 - dh ), 'D' );
    }
    else if( size.x == 0 )  /* vertical */
    {
        if( size.y < 0 )
            dh = -dh;
        Move_Plume_HPGL( wxPoint( pos_X0 - dh, pos_Y0 ), 'U' );
        Move_Plume_HPGL( wxPoint( pos_X1 - dh, pos_Y1 ), 'D' );
        Move_Plume_HPGL( wxPoint( pos_X1 + dh, pos_Y1 ), 'D' );
        Move_Plume_HPGL( wxPoint( pos_X0 + dh, pos_Y0 ), 'D' );
        Move_Plume_HPGL( wxPoint( pos_X0 - dh, pos_Y0 ), 'D' );
    }
    else    /* piste inclinee */
    {
        /* On calcule les coord des extremites du rectangle dans le repere
         *  a axe x confondu avec l'axe du rect. puis on revient dans le repere
         *  de trace par 2 rotations inverses
         *   coord :  xrot = x*cos + y*sin
         *            yrot = y*cos - x*sin
         *
         *  avec ici yrot = 0 puisque le segment est horizontal dans le nouveau repere
         *  Transformee inverse :
         *   coord :  x = xrot*cos - yrot*sin
         *            y = yrot*cos + xrot*sin
         */

        int dx0, dy0, dx1, dy1;

        if( size.x == size.y ) /* alpah = 45 degre */
        {
            sin_alpha = cos_alpha = 0.70711;
        }
        else if( size.x == -size.y ) /* alpah = -45 degre */
        {
            cos_alpha = 0.70711; sin_alpha = -0.70711;
        }
        else
        {
            alpha     = atan2( (double) size.y, (double) size.x );
            sin_alpha = sin( alpha );
            cos_alpha = cos( alpha );
        }

        dx_rot = (int) (size.x * cos_alpha + size.y * sin_alpha);
        /* size.y_rot = (int)(size.y * cos_alpha - size.x * sin_alpha) ; doit etre NULL */

        /* calcul du point de coord 0,-dh */
        dx0 = (int) ( dh * sin_alpha);
        dy0 = (int) (-dh * cos_alpha );
        Move_Plume_HPGL( wxPoint( pos_X0 + dx0, pos_Y0 + dy0 ), 'U' );

        /* calcul du point de coord size.xrot,-dh */
        dx1 = (int) (dx_rot * cos_alpha + dh * sin_alpha);
        dy1 = (int) (-dh * cos_alpha + dx_rot * sin_alpha );
        Move_Plume_HPGL( wxPoint( pos_X0 + dx1, pos_Y0 + dy1 ), 'D' );

        /* calcul du point de coord size.xrot,+dh */
        dx1 = (int) (dx_rot * cos_alpha - dh * sin_alpha);
        dy1 = (int) (dh * cos_alpha + dx_rot * sin_alpha );
        Move_Plume_HPGL( wxPoint( pos_X0 + dx1, pos_Y0 + dy1 ), 'D' );

        /* calcul du point de coord 0,+dh */
        dx1 = (int) ( -dh * sin_alpha);
        dy1 = (int) (dh * cos_alpha );
        Move_Plume_HPGL( wxPoint( pos_X0 + dx1, pos_Y0 + dy1 ), 'D' );

        /* retour au point de depart */
        Move_Plume_HPGL( wxPoint( pos_X0 + dx0, pos_Y0 + dy0 ), 'D' );
    }
    Plume_HPGL( 'U' );
}