kicad/pcbnew/plothpgl.cpp

874 lines
25 KiB
C++
Raw Normal View History

/*******************************/
/**** Routine de trace HPGL ****/
/*******************************/
#include "fctsys.h"
#include "common.h"
#include "plot_common.h"
#include "pcbnew.h"
#include "pcbplot.h"
#include "trigo.h"
#include "protos.h"
/* Variables locales : */
static int pen_rayon; /* Rayon de la plume en unites pcb */
static int pen_diam; /* Diametre de la plume en unites pcb */
static int pen_recouvrement; /* recouvrement en remplissage en unites pcb */
/* Routines Locales */
/*****************************************************************************/
void WinEDA_BasePcbFrame::Genere_HPGL(const wxString & FullFileName, int Layer)
/*****************************************************************************/
{
int modetrace;
wxSize SheetSize;
wxSize BoardSize;
wxPoint BoardCenter;
double scale_x, scale_y;
int marge = 0 * U_PCB; // Extra margin (set to 0)
bool Center = FALSE;
modetrace = Plot_Mode;
/* Calcul des echelles de conversion */
scale_x = Scale_X * SCALE_HPGL;
scale_y = Scale_Y * SCALE_HPGL;
// calcul en unites internes des dimensions de la feuille ( connues en 1/1000 pouce )
SheetSize.x = m_CurrentScreen->m_CurrentSheet->m_Size.x * U_PCB;
SheetSize.y = m_CurrentScreen->m_CurrentSheet->m_Size.y * U_PCB;
g_PlotOffset.x = 0 ;
g_PlotOffset.y = (int)(SheetSize.y * scale_y) ;
// 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
pen_diam = (int) round((g_HPGL_Pen_Diam * 10.0) / Scale_X); // Assume Scale_X # Scale_Y
pen_rayon = pen_diam / 2;
nb_plot_erreur = 0 ;
// compute pen_recouvrement (from g_HPGL_Pen_Recouvrement in mils)
// with plot scale
if(g_HPGL_Pen_Recouvrement < 0 ) g_HPGL_Pen_Recouvrement = 0 ;
if(g_HPGL_Pen_Recouvrement >= g_HPGL_Pen_Diam )
g_HPGL_Pen_Recouvrement = g_HPGL_Pen_Diam - 1 ;
pen_recouvrement = (int) round(g_HPGL_Pen_Recouvrement * 10.0/Scale_X);
dest = wxFopen(FullFileName, wxT("wt"));
if (dest == NULL)
{
wxString msg = _("Unable to create ") + FullFileName;
DisplayError(this, msg);
return ;
}
setlocale(LC_NUMERIC, "C");
Affiche_1_Parametre(this, 0,_("File"),FullFileName,CYAN) ;
PrintHeaderHPGL(dest, g_HPGL_Pen_Speed,g_HPGL_Pen_Num);
if ( Plot_Sheet_Ref && (g_PlotScaleOpt == 1) )
{
int tmp = g_PlotOrient; g_PlotOrient = 0;
InitPlotParametresHPGL(g_PlotOffset, scale_x, scale_y, g_PlotOrient);
PlotWorkSheet( PLOT_FORMAT_HPGL, m_CurrentScreen);
g_PlotOrient = tmp;
}
/* calcul des dimensions et centre du PCB */
m_Pcb->ComputeBoundaryBox();
BoardSize = m_Pcb->m_BoundaryBox.GetSize();
BoardCenter = m_Pcb->m_BoundaryBox.Centre();
if( g_PlotScaleOpt == 0 ) // Optimum scale
{
float Xscale, Yscale;
Xscale = (float) (SheetSize.x - ( 2 * marge)) / BoardSize.x;
Yscale = (float) (SheetSize.y - ( 2 * marge)) / BoardSize.y;
scale_x = scale_y = min( Xscale, Yscale) * SCALE_HPGL;
}
BoardCenter.x = (int)(BoardCenter.x * scale_x);
BoardCenter.y = (int)(BoardCenter.y * scale_y);
if( g_PlotScaleOpt != 1 ) Center = TRUE; // Echelle != 1
/* Calcul du cadrage */
marge = (int)(marge * SCALE_HPGL);
if ( Center )
g_PlotOffset.x = (int)(- SheetSize.x/2 * SCALE_HPGL) +
BoardCenter.x + marge;
switch ( g_PlotOrient)
{
default :
if ( Center )
{
g_PlotOffset.y = (int)(SheetSize.y/2 * SCALE_HPGL) +
BoardCenter.y + marge;
}
break ;
case PLOT_MIROIR :
if ( Center )
g_PlotOffset.y = (int)(- SheetSize.y/2 * SCALE_HPGL) + BoardCenter.y;
else g_PlotOffset.y = (int)((- SheetSize.y +
m_Pcb->m_BoundaryBox.GetBottom() + m_Pcb->m_BoundaryBox.GetY()) * SCALE_HPGL);
break ;
}
InitPlotParametresHPGL(g_PlotOffset, scale_x, scale_y, g_PlotOrient);
switch( Layer )
{
case CUIVRE_N :
case LAYER_N_2 :
case LAYER_N_3 :
case LAYER_N_4 :
case LAYER_N_5 :
case LAYER_N_6 :
case LAYER_N_7 :
case LAYER_N_8 :
case LAYER_N_9 :
case LAYER_N_10 :
case LAYER_N_11:
case LAYER_N_12:
case LAYER_N_13 :
case LAYER_N_14 :
case LAYER_N_15 :
case CMP_N : Plot_Layer_HPGL(dest,g_TabOneLayerMask[Layer], 0, 1, modetrace);
break;
case SILKSCREEN_N_CU :
case SILKSCREEN_N_CMP :
Plot_Serigraphie(PLOT_FORMAT_HPGL,dest, g_TabOneLayerMask[Layer]);
break;
case SOLDERMASK_N_CU :
case SOLDERMASK_N_CMP : /* Trace du vernis epargne */
{
int tracevia;
if (g_DrawViaOnMaskLayer) tracevia = 1;
else tracevia = 0;
Plot_Layer_HPGL(dest,g_TabOneLayerMask[Layer],
g_DesignSettings.m_MaskMargin, tracevia, modetrace);
}
break;
case SOLDERPASTE_N_CU :
case SOLDERPASTE_N_CMP : /* Trace du masque de pate de soudure */
Plot_Layer_HPGL(dest,g_TabOneLayerMask[Layer], 0, 0, modetrace);
break;
default : /* Trace des autres couches (dessin, adhesives,eco,comment) */
Plot_Serigraphie(PLOT_FORMAT_HPGL,dest, g_TabOneLayerMask[Layer]);
break;
}
/* fin */
CloseFileHPGL(dest) ;
setlocale(LC_NUMERIC, "");
}
/*********************************************************************/
void WinEDA_BasePcbFrame::Plot_Layer_HPGL(FILE * File,int masque_layer,
int garde, int tracevia, int modetrace)
/*********************************************************************/
/* Trace en format HPGL. d'une couche cuivre ou masque
1 unite HPGL = 0.98 mils ( 1 mil = 1.02041 unite HPGL ) .
*/
{
wxSize size;
wxPoint start, end;
MODULE * Module;
D_PAD * PtPad;
TRACK * pts ;
EDA_BaseStruct * PtStruct;
wxString msg;
masque_layer |= EDGE_LAYER; /* Les elements de la couche EDGE sont tj traces */
/* trace des elements type Drawings Pcb : */
PtStruct = m_Pcb->m_Drawings;
for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
{
switch( PtStruct->m_StructType )
{
case TYPEDRAWSEGMENT:
PlotDrawSegment( (DRAWSEGMENT*) PtStruct, PLOT_FORMAT_HPGL,
masque_layer);
break;
case TYPETEXTE:
PlotTextePcb((TEXTE_PCB*) PtStruct,PLOT_FORMAT_HPGL,
masque_layer);
break;
case TYPECOTATION:
PlotCotation((COTATION*) PtStruct, PLOT_FORMAT_HPGL,
masque_layer);
break;
case TYPEMIRE:
PlotMirePcb((MIREPCB*) PtStruct, PLOT_FORMAT_HPGL,
masque_layer);
break;
case TYPEMARQUEUR:
break;
default:
DisplayError(this, wxT("Type Draw non gere"));
break;
}
}
/* Trace des Elements des modules autres que pads */
nb_items = 0 ;
Affiche_1_Parametre(this, 48, wxT("DrawMod"),wxEmptyString,GREEN) ;
Module = m_Pcb->m_Modules;
for( ; Module != NULL ;Module = (MODULE *)Module->Pnext )
{
PtStruct = Module->m_Drawings;
for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
{
switch( PtStruct->m_StructType )
{
case TYPEEDGEMODULE:
if( masque_layer &
g_TabOneLayerMask[((EDGE_MODULE*)PtStruct)->m_Layer] )
Plot_1_EdgeModule(PLOT_FORMAT_HPGL, (EDGE_MODULE*) PtStruct);
break;
default: break;
}
}
}
/* Trace des Elements des modules : Pastilles */
nb_items = 0 ;
Affiche_1_Parametre(this, 48, wxT("Pads "), wxEmptyString,GREEN) ;
Module = m_Pcb->m_Modules;
for( ; Module != NULL ; Module = (MODULE*) Module->Pnext)
{
PtPad = (D_PAD*) Module->m_Pads;
for ( ; PtPad != NULL ;PtPad = (D_PAD*)PtPad->Pnext )
{
wxPoint shape_pos;
if( (PtPad->m_Masque_Layer & masque_layer) == 0)
continue ;
shape_pos = PtPad->ReturnShapePos();
start = shape_pos;
size = PtPad->m_Size;
size.x += garde*2; size.y += garde*2;
nb_items++ ;
switch (PtPad->m_PadShape & 0x7F)
{
case CIRCLE :
trace_1_pastille_RONDE_HPGL(start,size.x,modetrace) ;
break ;
case OVALE :
{
trace_1_pastille_OVALE_HPGL(start,size, PtPad->m_Orient,modetrace) ;
break ;
}
case TRAPEZE :
{
wxSize delta;
delta = PtPad->m_DeltaSize;
trace_1_pad_TRAPEZE_HPGL(start,size,delta,
PtPad->m_Orient, modetrace) ;
break ;
}
case RECT :
default:
PlotRectangularPad_HPGL(start,size,
PtPad->m_Orient,modetrace) ;
break ;
}
msg.Printf( wxT("%d"),nb_items) ;
Affiche_1_Parametre(this, 48, wxT("Pads"), msg,GREEN) ;
}
}
/* trace des VIAS : */
if(tracevia)
{
TRACK * pts ;
nb_items = 0 ;
Affiche_1_Parametre(this, 56, wxT("Vias"), wxEmptyString, RED) ;
for(pts = m_Pcb->m_Track ;pts != NULL; pts = (TRACK*)pts->Pnext )
{
if( pts->m_StructType != TYPEVIA ) continue;
SEGVIA * Via = (SEGVIA *) pts;
/* vias not plotted if not on selected layer, but if layer
== SOLDERMASK_LAYER_CU or SOLDERMASK_LAYER_CMP, vias are drawn ,
if they are on a external copper layer
*/
int via_mask_layer = Via->ReturnMaskLayer();
if ( (via_mask_layer & CUIVRE_LAYER ) ) via_mask_layer |= SOLDERMASK_LAYER_CU;
if ( (via_mask_layer & CMP_LAYER ) ) via_mask_layer |= SOLDERMASK_LAYER_CMP;
if( (via_mask_layer & masque_layer) == 0 ) continue;
start = Via->m_Start;
size.x = Via->m_Width + (garde*2);
trace_1_pastille_RONDE_HPGL(start, size.x, modetrace) ;
nb_items++ ; msg.Printf( wxT("%d"), nb_items) ;
Affiche_1_Parametre(this, 56, wxT("Vias"), msg,RED) ;
}
fputs("PU;\n",dest) ;
}
/* trace des segments pistes */
nb_items = 0 ;
Affiche_1_Parametre(this, 64, wxT("Tracks "),wxEmptyString,YELLOW) ;
for(pts = m_Pcb->m_Track ;pts != NULL; pts = (TRACK*)pts->Pnext )
{
if ( pts->m_StructType == TYPEVIA ) continue ;
if( (g_TabOneLayerMask[pts->m_Layer] & 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( (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) ;
nb_items++ ; msg.Printf( wxT("%d"),nb_items) ;
Affiche_1_Parametre(this, 64,wxEmptyString, msg,YELLOW) ;
}
/* trace des segments pistes et zones */
nb_items = 0 ;
Affiche_1_Parametre(this, 64, wxT("Zones "), wxEmptyString,YELLOW) ;
for(pts = m_Pcb->m_Zone ;pts != NULL; pts = (TRACK*)pts->Pnext )
{
if( g_TabOneLayerMask[pts->m_Layer] & masque_layer)
{
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( (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) ;
nb_items++ ; msg.Printf( wxT("%d"),nb_items) ;
Affiche_1_Parametre(this, 64,wxEmptyString, msg,YELLOW) ;
}
}
}
/************************************************************************************/
void trace_1_pastille_OVALE_HPGL(wxPoint pos, wxSize size, int orient, int modetrace)
/************************************************************************************/
/* Trace 1 pastille OVALE 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;
}
deltaxy = size.y - size.x; /* = distance entre centres de l'ovale */
rayon = size.x / 2;
if ( modetrace == FILLED )
{
PlotRectangularPad_HPGL(pos, wxSize(size.x,deltaxy),
orient,modetrace) ;
cx = 0; cy = deltaxy/2;
RotatePoint(&cx, &cy, trace_orient);
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);
trace_1_pastille_RONDE_HPGL(wxPoint(cx + pos.x, cy + pos.y), size.x, modetrace) ;
}
else /* Trace en mode FILAIRE */
{
cx = -rayon; cy = -deltaxy / 2;
RotatePoint(&cx, &cy, trace_orient);
Move_Plume_HPGL( wxPoint(cx + pos.x, cy + pos.y), 'U');
cx = -rayon; cy = deltaxy / 2;
RotatePoint(&cx, &cy, trace_orient);
Move_Plume_HPGL( wxPoint(cx + pos.x, cy + pos.y), 'D');
cx = rayon; cy = - deltaxy / 2;
RotatePoint(&cx, &cy, trace_orient);
Move_Plume_HPGL( wxPoint(cx + pos.x, cy + pos.y), 'U');
cx = rayon; cy = deltaxy / 2;
RotatePoint(&cx, &cy, trace_orient);
Move_Plume_HPGL( wxPoint(cx + pos.x, cy + pos.y), 'D');
Plume_HPGL('U');
cx = 0; cy = - deltaxy / 2;
RotatePoint(&cx, &cy, trace_orient);
PlotArc(PLOT_FORMAT_HPGL, wxPoint(cx + pos.x, cy + pos.y),
trace_orient, trace_orient + 1800,
size.x / 2, pen_diam);
cx = 0; cy = deltaxy / 2;
RotatePoint(&cx, &cy, trace_orient);
PlotArc(PLOT_FORMAT_HPGL, wxPoint(cx + pos.x, cy + pos.y),
trace_orient + 1800, trace_orient,
size.x / 2, pen_diam);
}
Plume_HPGL('U') ;
}
/**************************************************************************/
void trace_1_pastille_RONDE_HPGL(wxPoint pos, int diametre, int modetrace)
/**************************************************************************/
/* Trace 1 pastille RONDE (via,pad rond) en position pos */
{
int rayon, delta;
UserToDeviceCoordinate(pos);
delta = pen_diam - pen_recouvrement;
rayon = diametre / 2 ;
if(modetrace != FILAIRE)
{
rayon = (diametre - pen_diam ) /2 ;
}
if(rayon < 0 )
{
rayon = 0 ; nb_plot_erreur++ ; Affiche_erreur(nb_plot_erreur) ;
}
wxSize rsize(rayon, rayon);
UserToDeviceSize( rsize );
Plume_HPGL('U');
sprintf(cbuf,"PA %d,%d;CI %d;\n", pos.x, pos.y, rsize.x);
fputs(cbuf,dest) ;
if(modetrace == FILLED ) /* Trace en mode Remplissage */
{
if(delta > 0 )
{
while ( (rayon -= delta ) >= 0 )
{
rsize.x = rsize.y = rayon;
UserToDeviceSize( rsize );
sprintf(cbuf,"PA %d,%d; CI %d;\n", pos.x, pos.y, rsize.x);
fputs(cbuf,dest) ;
}
}
}
Plume_HPGL('U'); return ;
}
/***************************************************************/
void PlotRectangularPad_HPGL(wxPoint padpos, wxSize padsize,
int orient,int modetrace)
/****************************************************************/
/*
Trace 1 pad rectangulaire vertical ou horizontal ( Pad rectangulaire )
donne par son centre et ses dimensions X et Y
Units are user units
*/
{
wxSize size;
int delta;
int ox, oy, fx, fy;
size.x = padsize.x / 2; size.y = padsize.y / 2 ;
if(modetrace != FILAIRE)
{
size.x = (padsize.x - (int)pen_diam) / 2 ;
size.y = (padsize.y - (int)pen_diam) / 2 ;
}
if ( (size.x < 0 ) || (size.y < 0) )
{
nb_plot_erreur++ ; Affiche_erreur(nb_plot_erreur) ;
}
if ( size.x < 0 ) size.x = 0 ; if ( size.y < 0 ) size.y = 0 ;
/* Si une des dimensions est nulle, le trace se reduit a 1 trait */
if(size.x == 0 )
{
ox = padpos.x; oy = padpos.y-size.y;
RotatePoint(&ox,&oy,padpos.x,padpos.y,orient);
fx = padpos.x; fy = padpos.y+size.y;
RotatePoint(&fx,&fy,padpos.x,padpos.y,orient);
Move_Plume_HPGL( wxPoint(ox, oy), 'U');
Move_Plume_HPGL( wxPoint(fx, fy), 'D');
Plume_HPGL('U'); return ;
}
if(size.y == 0 )
{
ox = padpos.x - size.x; oy = padpos.y;
RotatePoint(&ox,&oy,padpos.x,padpos.y,orient);
fx = padpos.x + size.x; fy = padpos.y;
RotatePoint(&fx,&fy,padpos.x,padpos.y,orient);
Move_Plume_HPGL( wxPoint(ox, oy), 'U');
Move_Plume_HPGL( wxPoint(fx, fy), 'D');
Plume_HPGL('U') ; return ;
}
ox = padpos.x - size.x; oy = padpos.y - size.y;
RotatePoint(&ox,&oy,padpos.x,padpos.y,orient);
Move_Plume_HPGL( wxPoint(ox, oy), 'U');
fx = padpos.x - size.x; fy = padpos.y + size.y;
RotatePoint(&fx,&fy,padpos.x,padpos.y,orient);
Move_Plume_HPGL( wxPoint(fx, fy), 'D');
fx = padpos.x + size.x; fy = padpos.y + size.y;
RotatePoint(&fx,&fy,padpos.x,padpos.y,orient);
Move_Plume_HPGL( wxPoint(fx, fy), 'D');
fx = padpos.x + size.x; fy = padpos.y - size.y;
RotatePoint(&fx,&fy,padpos.x,padpos.y,orient);
Move_Plume_HPGL( wxPoint(fx, fy), 'D');
Move_Plume_HPGL( wxPoint(ox, oy), 'D');
if(modetrace != FILLED )
{
Plume_HPGL('U'); return ;
}
/* Trace en mode Remplissage */
delta = (int)(pen_diam - pen_recouvrement) ;
if(delta > 0 )
while( (size.x > 0) && (size.y > 0) )
{
size.x -= delta; size.y -= delta ;
if ( size.x < 0 ) size.x = 0 ; if ( size.y < 0 ) size.y = 0 ;
ox = padpos.x - size.x; oy = padpos.y - size.y;
RotatePoint(&ox,&oy,padpos.x,padpos.y,orient);
Move_Plume_HPGL( wxPoint(ox, oy), 'D');
fx = padpos.x - size.x; fy = padpos.y + size.y;
RotatePoint(&fx,&fy,padpos.x,padpos.y,orient);
Move_Plume_HPGL( wxPoint(fx, fy), 'D');
fx = padpos.x + size.x; fy = padpos.y + size.y;
RotatePoint(&fx,&fy,padpos.x,padpos.y,orient);
Move_Plume_HPGL( wxPoint(fx, fy), 'D');
fx = padpos.x + size.x; fy = padpos.y - size.y;
RotatePoint(&fx,&fy,padpos.x,padpos.y,orient);
Move_Plume_HPGL( wxPoint(fx, fy), 'D');
Move_Plume_HPGL( wxPoint(ox, oy), 'D');
}
Plume_HPGL('U');
}
/********************************************************************/
void trace_1_pad_TRAPEZE_HPGL(wxPoint padpos, wxSize size,wxSize delta,
int orient,int modetrace)
/********************************************************************/
/*
Trace 1 pad trapezoidal donne par :
son centre padpos.x,padpos.y
ses dimensions dimX et dimY
les variations deltaX et deltaY
son orientation orient et 0.1 degres
le mode de trace (FILLED, SKETCH, FILAIRE)
Le trace n'est fait que pour un trapeze, c.a.d que deltaX ou deltaY
= 0.
les notation des sommets sont ( vis a vis de la table tracante )
0 ------------- 3
. .
. .
. .
1 --- 2
*/
{
int ii , jj;
wxPoint polygone[4]; /* coord des sommets / centre du pad */
wxPoint coord[4]; /* coord reelles des sommets du trapeze a tracer */
float fangle; /* angle d'inclinaison des cotes du trapeze */
int rayon; /* rayon de la plume */
int moveX, moveY; /* variation de position plume selon axe X et Y , lors
du remplissage du trapeze */
rayon = (int) pen_rayon; if (modetrace == FILAIRE) rayon = 0;
moveX = moveY = rayon;
size.x /= 2; size.y /= 2;
delta.x /= 2; delta.y /= 2;
polygone[0].x = - size.x - delta.y; polygone[0].y = + size.y + delta.x;
polygone[1].x = - size.x + delta.y; polygone[1].y = - size.y - delta.x;
polygone[2].x = + size.x - delta.y; polygone[2].y = - size.y + delta.x;
polygone[3].x = + size.x + delta.y; polygone[3].y = + size.y - delta.x;
/* Calcul du demi angle d'inclinaison des cotes du trapeze */
if( delta.y ) /* Trapeze horizontal */
{
fangle = atan2( (float)(polygone[1].y - polygone[0].y),
(float)(polygone[1].x - polygone[0].x) ) / 2 ;
}
else
{
fangle = atan2( (float)(polygone[3].y - polygone[0].y),
(float)(polygone[3].x - polygone[0].x) ) / 2 ;
}
/* Trace du contour */
polygone[0].x += moveX; polygone[0].y -= moveY;
polygone[1].x += moveX; polygone[1].y += moveY;
polygone[2].x -= moveX; polygone[2].y += moveY;
polygone[3].x -= moveX; polygone[3].y -= moveY;
for (ii = 0; ii < 4; ii++)
{
coord[ii].x = polygone[ii].x + padpos.x;
coord[ii].y = polygone[ii].y + padpos.y;
RotatePoint(&coord[ii], padpos, orient);
}
// Plot edge:
Move_Plume_HPGL( coord[0], 'U');
Move_Plume_HPGL( coord[1], 'D');
Move_Plume_HPGL( coord[2], 'D');
Move_Plume_HPGL( coord[3], 'D');
Move_Plume_HPGL( coord[0], 'D');
if(modetrace != FILLED )
{
Plume_HPGL('U'); return;
}
/* Fill the shape */
moveX = moveY = pen_diam - pen_recouvrement;
/* calcul de jj = hauteur du remplissage */
if( delta.y ) /* Trapeze horizontal */
{
jj = size.y - (int)( pen_diam + (2 * pen_recouvrement) );
}
else
{
jj = size.x - (int)( pen_diam + (2 * pen_recouvrement) );
}
/* Calcul de jj = nombre de segments a tracer pour le remplissage */
jj = jj / (int)(pen_diam - pen_recouvrement);
/* Trace du contour */
for( ; jj > 0 ; jj-- )
{
polygone[0].x += moveX; polygone[0].y -= moveY;
polygone[1].x += moveX; polygone[1].y += moveY;
polygone[2].x -= moveX; polygone[2].y += moveY;
polygone[3].x -= moveX; polygone[3].y -= moveY;
/* Test de limitation de variation des dimensions :
si les sommets se "croisent", il ne faut plus modifier les
coordonnees correspondantes */
if( polygone[0].x > polygone[3].x )
{ /* croisement sur axe X des 2 sommets 0 et 3 */
polygone[0].x = polygone[3].x = 0;
}
if( polygone[1].x > polygone[2].x )
{ /* croisement sur axe X des 2 sommets 1 et 2 */
polygone[1].x = polygone[2].x = 0;
}
if( polygone[1].y > polygone[0].y )
{ /* croisement sur axe Y des 2 sommets 0 et 1 */
polygone[0].y = polygone[1].y = 0;
}
if( polygone[2].y > polygone[3].y )
{ /* croisement sur axe Y des 2 sommets 2 et 3 */
polygone[2].y = polygone[3].y = 0;
}
for (ii = 0; ii < 4; ii++)
{
coord[ii].x = polygone[ii].x + padpos.x;
coord[ii].y = polygone[ii].y + padpos.y;
RotatePoint(&coord[ii], padpos, orient);
}
Move_Plume_HPGL( coord[0], 'U');
Move_Plume_HPGL( coord[1], 'D');
Move_Plume_HPGL( coord[2], 'D');
Move_Plume_HPGL( coord[3], 'D');
Move_Plume_HPGL( coord[0], 'D');
}
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 ; nb_plot_erreur++ ; Affiche_erreur(nb_plot_erreur) ;
}
if ( (dh == 0) || (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((float)size.y,(float)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');
}