From 3e477651c7666c2259e2f959a59acce788ebd7d5 Mon Sep 17 00:00:00 2001 From: charras Date: Wed, 18 Mar 2009 15:38:16 +0000 Subject: [PATCH] finishing work on hpgl plotting functions --- pcbnew/pcbplot.h | 164 ++++++++++++++------------- pcbnew/plot_rtn.cpp | 233 ++++++++++++++++++++++---------------- pcbnew/plothpgl.cpp | 270 +++++++++++++------------------------------- 3 files changed, 304 insertions(+), 363 deletions(-) diff --git a/pcbnew/pcbplot.h b/pcbnew/pcbplot.h index 08d0bd4796..e1eb037108 100644 --- a/pcbnew/pcbplot.h +++ b/pcbnew/pcbplot.h @@ -1,6 +1,6 @@ - /************/ - /* pcbplot.h*/ - /************/ +/************/ +/* pcbplot.h*/ +/************/ #ifndef PCBPLOT_H #define PCBPLOT_H @@ -12,10 +12,10 @@ /* Shared Config keys for plot and print */ #define OPTKEY_PLOT_LINEWIDTH_VALUE wxT( "PlotLineWidth" ) -#define OPTKEY_LAYERBASE wxT( "PlotLayer_%d" ) -#define OPTKEY_PRINT_X_FINESCALE_ADJ wxT( "PrintXFineScaleAdj" ) -#define OPTKEY_PRINT_Y_FINESCALE_ADJ wxT( "PrintYFineScaleAdj" ) -#define OPTKEY_PRINT_SCALE wxT( "PrintScale" ) +#define OPTKEY_LAYERBASE wxT( "PlotLayer_%d" ) +#define OPTKEY_PRINT_X_FINESCALE_ADJ wxT( "PrintXFineScaleAdj" ) +#define OPTKEY_PRINT_Y_FINESCALE_ADJ wxT( "PrintYFineScaleAdj" ) +#define OPTKEY_PRINT_SCALE wxT( "PrintScale" ) /* Constantes de conversion d'unites */ /* coeff de conversion dim en 0.1 mil -> dim en unite PS: (unite PS = pouce) */ @@ -24,23 +24,23 @@ #define SCALE_HPGL 0.102041 /* Options : */ -eda_global bool g_Exclude_Edges_Pcb // True to exclude contents of Edges Pcb layer +eda_global bool g_Exclude_Edges_Pcb // True to exclude contents of Edges Pcb layer #ifdef MAIN = FALSE #endif ; eda_global bool g_Plot_Frame_Ref; // True to plot/print frame references -eda_global bool g_DrawViaOnMaskLayer; // True if vias are drawn on Mask layer (ie protected by mask) -eda_global int g_Plot_Mode // = FILAIRE, FILL or SKETCH +eda_global bool g_DrawViaOnMaskLayer; // True if vias are drawn on Mask layer (ie protected by mask) +eda_global int g_Plot_Mode // = FILAIRE, FILL or SKETCH #ifdef MAIN = FILLED #endif ; -eda_global bool Plot_Set_MIROIR ; +eda_global bool Plot_Set_MIROIR; eda_global bool Sel_Rotate_Window; -eda_global bool HPGL_Org_Centre; // TRUE si en HPGL, l'origine le centre de la feuille -eda_global int g_PlotPSColorOpt; // True for color Postscript output -eda_global bool g_Plot_PS_Negative; // True to create a negative board ps plot +eda_global bool HPGL_Org_Centre; // TRUE si en HPGL, l'origine le centre de la feuille +eda_global int g_PlotPSColorOpt; // True for color Postscript output +eda_global bool g_Plot_PS_Negative; // True to create a negative board ps plot /* Autorisation de trace des divers items en serigraphie */ @@ -60,50 +60,50 @@ eda_global bool Sel_Texte_Divers #endif ; eda_global bool Sel_Texte_Invisible; -eda_global bool PlotPadsOnSilkLayer /* Plot pads sur couche serigraphie */ +eda_global bool PlotPadsOnSilkLayer /* Plot pads sur couche serigraphie */ #ifdef MAIN = TRUE #endif ; -eda_global bool Plot_Pads_All_Layers; /* Plot pads meme n'appartenant pas a la - couche ( utile pour serigraphie) */ +eda_global bool Plot_Pads_All_Layers; /* Plot pads meme n'appartenant pas a la + * couche ( utile pour serigraphie) */ - /* Variables utiles */ +/* Variables utiles */ -eda_global FILE * dest; +eda_global FILE* dest; /* Gestion des plumes en plot format HPGL */ -eda_global int g_HPGL_Pen_Num /* num de plume a charger */ +eda_global int g_HPGL_Pen_Num /* num de plume a charger */ #ifdef MAIN = 1 #endif ; -eda_global int g_HPGL_Pen_Speed /* vitesse en cm/s */ +eda_global int g_HPGL_Pen_Speed /* vitesse en cm/s */ #ifdef MAIN = 40 #endif ; -eda_global int g_HPGL_Pen_Diam; /* diametre en mils */ -eda_global int g_HPGL_Pen_Recouvrement; /* recouvrement en mils ( pour remplissages */ +eda_global int g_HPGL_Pen_Diam; /* diametre en mils */ +eda_global int g_HPGL_Pen_Recouvrement; /* recouvrement en mils ( pour remplissages */ /* Gestion des cadrages et echelles de trace */ -eda_global float Scale_X, Scale_Y ; /* coeff d'agrandissement en X et Y demandes */ -eda_global wxPoint g_PlotOffset; /* Offset de trace modifies par l'echelle */ +eda_global float Scale_X, Scale_Y; /* coeff d'agrandissement en X et Y demandes */ +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) */ +eda_global int g_PlotLine_Width; /* Largeur du trait en mode filaire (utilise en serigraphie, + * pour traces en mode sketch et filaire) */ -eda_global int g_PlotFormat /* id for plot format (see enum PlotFormat in plot_common.h) */ +eda_global int g_PlotFormat /* id for plot format (see enum PlotFormat in plot_common.h) */ #ifdef MAIN = PLOT_FORMAT_GERBER #endif ; eda_global int g_PlotOrient; /* numero de code de l'orientation du trace ( voir - defines precedents): - 0 = normal - PLOT_MIROIR = MIROIR - */ -eda_global int g_PlotScaleOpt // 0 = automatique, >=1 echelle specifiee + * defines precedents): + * 0 = normal + * PLOT_MIROIR = MIROIR + */ +eda_global int g_PlotScaleOpt // 0 = automatique, >=1 echelle specifiee #ifdef MAIN = 1 #endif @@ -111,73 +111,81 @@ eda_global int g_PlotScaleOpt // 0 = automatique, >=1 echelle specifiee eda_global int g_DrillShapeOpt #ifdef MAIN - = 1 // 0 = no drill mark, 1 = small mark, 2 = real drill += 1 // 0 = no drill mark, 1 = small mark, 2 = real drill #endif ; - /*************************************/ - /* Constantes utiles en trace GERBER */ - /*************************************/ +/*************************************/ +/* Constantes utiles en trace GERBER */ +/*************************************/ /* codes de type de forme d'outils */ #define GERB_CIRCLE 1 -#define GERB_RECT 2 -#define GERB_LINE 3 -#define GERB_OVALE 4 -#define GERB_DONUT 5 +#define GERB_RECT 2 +#define GERB_LINE 3 +#define GERB_OVALE 4 +#define GERB_DONUT 5 /* 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 */ -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); -void PlotFilledPolygon(int format_plot, int nbpoints, int * coord); -void PlotPolygon(int format_plot, int nbpoints, int * coord, int width); +void PlotTextePcb( TEXTE_PCB* pt_texte, int format_plot, int masque_layer ); -void PlotDrawSegment( DRAWSEGMENT* PtSegm, 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 */ +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 ); +void PlotFilledPolygon( int format_plot, int nbpoints, int* coord ); +void PlotPolygon( int format_plot, int nbpoints, int* coord, int width ); -void PlotCotation( COTATION * Cotation, int format_plot,int masque_layer ); +void PlotDrawSegment( DRAWSEGMENT* PtSegm, int format_plot, int masque_layer ); -void PlotMirePcb( MIREPCB* PtMire, int format_plot,int masque_layer ); +void PlotCotation( COTATION* Cotation, int format_plot, int masque_layer ); -void Plot_1_EdgeModule(int format_plot, EDGE_MODULE * PtEdge); +void PlotMirePcb( MIREPCB* PtMire, int format_plot, int masque_layer ); -void PlotFilledAreas( ZONE_CONTAINER * aZone, int aFormat); +void Plot_1_EdgeModule( int format_plot, EDGE_MODULE* PtEdge ); + +void PlotFilledAreas( ZONE_CONTAINER* aZone, int aFormat ); /* PLOTGERB.CPP */ -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 */ +void SelectD_CODE_For_LineDraw( int aSize ); +void trace_1_contour_GERBER( wxPoint pos, wxSize size, wxSize delta, + int penwidth, int orient ); -/* PLOTHPGL.CC */ -void trace_1_segment_HPGL(int pos_X0,int pos_Y0,int pos_X1,int pos_Y1, - int hauteur); +/* 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 */ -void trace_1_pad_TRAPEZE_HPGL(wxPoint padpos, wxSize size,wxSize delta, - int orient,int modetrace); +/* PLOTHPGL.CPP */ -void trace_1_pastille_RONDE_HPGL(wxPoint padpos, int diametre,int modetrace) ; -void trace_1_pastille_OVALE_HPGL(wxPoint padpos, wxSize size, int orient, int modetrace); -void PlotRectangularPad_HPGL(wxPoint padpos, wxSize padsize, int orient,int modetrace); +/** 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 ); + +void trace_1_pastille_RONDE_HPGL( wxPoint padpos, int diametre, int modetrace ); +void trace_1_pastille_OVALE_HPGL( wxPoint padpos, wxSize size, int orient, int modetrace ); +void PlotRectangularPad_HPGL( wxPoint padpos, wxSize padsize, int orient, int modetrace ); /**************/ /* PLOTPS.CPP */ /**************/ -void trace_1_pastille_OVALE_POST(wxPoint centre, wxSize size, int orient, int modetrace); -void trace_1_pastille_RONDE_POST(wxPoint centre, int diametre, int modetrace); -void trace_1_pad_rectangulaire_POST(wxPoint centre, wxSize size,int orient, - int modetrace); -void trace_1_contour_POST(wxPoint centre, wxSize size, wxSize delta, - int dim_trait, int orient); -void trace_1_pad_TRAPEZE_POST(wxPoint centre, wxSize size, wxSize delta, - int orient,int modetrace); +void trace_1_pastille_OVALE_POST( wxPoint centre, wxSize size, int orient, int modetrace ); +void trace_1_pastille_RONDE_POST( wxPoint centre, int diametre, int modetrace ); +void trace_1_pad_rectangulaire_POST( wxPoint centre, wxSize size, int orient, + int modetrace ); +void trace_1_contour_POST( wxPoint centre, wxSize size, wxSize delta, + int dim_trait, int orient ); +void trace_1_pad_TRAPEZE_POST( wxPoint centre, wxSize size, wxSize delta, + int orient, int modetrace ); -#endif /* #define PCBPLOT_H */ - +#endif /* #define PCBPLOT_H */ diff --git a/pcbnew/plot_rtn.cpp b/pcbnew/plot_rtn.cpp index 75c267d07b..00097b4f52 100644 --- a/pcbnew/plot_rtn.cpp +++ b/pcbnew/plot_rtn.cpp @@ -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; } } @@ -200,8 +204,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 \"reference\" text."), - textLayer, Module->GetReference().GetData() ); + _( "Your BOARD has a bad layer number of %u for module\n %s's \"reference\" text." ), + textLayer, Module->GetReference().GetData() ); DisplayError( this, errMsg ); goto exit; } @@ -220,8 +224,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 \"value\" text."), - textLayer, Module->GetReference().GetData() ); + _( "Your BOARD has a bad layer number of %u for module\n %s's \"value\" text." ), + textLayer, Module->GetReference().GetData() ); DisplayError( this, errMsg ); goto exit; } @@ -260,13 +264,14 @@ 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."), - textLayer, Module->GetReference().GetData(), pt_texte->m_Text.GetData() ); + _( + "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; } - if( !( (1<GetAreaCount(); ii++ ) { - ZONE_CONTAINER* edge_zone = m_Pcb->GetArea(ii); - if( ( (1 << edge_zone->GetLayer()) & masque_layer ) == 0 ) + ZONE_CONTAINER* edge_zone = m_Pcb->GetArea( ii ); + if( ( ( 1 << edge_zone->GetLayer() ) & masque_layer ) == 0 ) continue; - PlotFilledAreas(edge_zone, format_plot); + PlotFilledAreas( edge_zone, format_plot ); } exit: @@ -306,27 +311,27 @@ static void PlotTextModule( TEXTE_MODULE* pt_texte, int format_plot ) thickness = g_PlotLine_Width; if( pt_texte->m_Mirror ) - size.x = -size.x; // Text is mirrored + size.x = -size.x; // Text is mirrored switch( format_plot ) { - case PLOT_FORMAT_GERBER: - SelectD_CODE_For_LineDraw(thickness); - break; + case PLOT_FORMAT_GERBER: + SelectD_CODE_For_LineDraw( thickness ); + break; - case PLOT_FORMAT_HPGL: - break; + case PLOT_FORMAT_HPGL: + break; - case PLOT_FORMAT_POST: - SetCurrentLineWidthPS( thickness ); - break; + case PLOT_FORMAT_POST: + SetCurrentLineWidthPS( thickness ); + break; } PlotGraphicText( format_plot, pos, BLACK, - pt_texte->m_Text, - orient, size, - pt_texte->m_HJustify, pt_texte->m_VJustify, - thickness, pt_texte->m_Italic ); + pt_texte->m_Text, + orient, size, + pt_texte->m_HJustify, pt_texte->m_VJustify, + thickness, pt_texte->m_Italic ); } @@ -402,7 +407,7 @@ void PlotMirePcb( MIREPCB* Mire, int format_plot, int masque_layer ) DrawTmp->m_Shape = S_SEGMENT; /* Trace des 2 traits */ radius = Mire->m_Size / 2; - dx1 = radius, dy1 = 0; dx2 = 0, dy2 = radius; + dx1 = radius, dy1 = 0; dx2 = 0, dy2 = radius; if( Mire->m_Shape ) /* Forme X */ { @@ -428,8 +433,8 @@ void Plot_Edges_Modules( BOARD* pcb, int format_plot, int masque_layer ) /**********************************************************************/ /* Trace les contours des modules */ { - int nb_items; /* Pour affichage activite: nbr modules traites */ - wxString msg; + int nb_items; /* Pour affichage activite: nbr modules traites */ + wxString msg; nb_items = 0; for( MODULE* module = pcb->m_Modules; module; module = module->Next() ) @@ -458,11 +463,11 @@ void Plot_1_EdgeModule( int format_plot, EDGE_MODULE* PtEdge ) /**************************************************************/ /* Trace les contours des modules */ { - int type_trace; /* forme a tracer (segment, cercle) */ - int thickness; /* thickness des segments */ - int radius; /* radius des cercles a tracer */ + int type_trace; /* forme a tracer (segment, cercle) */ + int thickness; /* thickness des segments */ + int radius; /* radius des cercles a tracer */ int StAngle, EndAngle; - wxPoint pos, end; /* Coord des segments a tracer */ + wxPoint pos, end; /* Coord des segments a tracer */ if( PtEdge->Type() != TYPE_EDGE_MODULE ) return; @@ -473,7 +478,7 @@ void Plot_1_EdgeModule( int format_plot, EDGE_MODULE* PtEdge ) if( g_Plot_Mode == FILAIRE ) { thickness = g_PlotLine_Width; - wxLogDebug( wxT("changing edgemodule thickness to g_PlotLine_Width") ); + wxLogDebug( wxT( "changing edgemodule thickness to g_PlotLine_Width" ) ); } pos = PtEdge->m_Start; @@ -487,12 +492,12 @@ void Plot_1_EdgeModule( int format_plot, EDGE_MODULE* PtEdge ) switch( format_plot ) { case PLOT_FORMAT_GERBER: - SelectD_CODE_For_LineDraw(thickness); + SelectD_CODE_For_LineDraw( thickness ); PlotGERBERLine( pos, end, thickness ); 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: @@ -508,7 +513,7 @@ void Plot_1_EdgeModule( int format_plot, EDGE_MODULE* PtEdge ) break; case S_ARC: - radius = (int) hypot( (double) (end.x - pos.x), (double) (end.y - pos.y) ); + radius = (int) hypot( (double) (end.x - pos.x), (double) (end.y - pos.y) ); StAngle = ArcTangente( end.y - pos.y, end.x - pos.x ); EndAngle = StAngle + PtEdge->m_Angle; if( StAngle > EndAngle ) @@ -517,40 +522,40 @@ void Plot_1_EdgeModule( int format_plot, EDGE_MODULE* PtEdge ) break; case S_POLYGON: + { + // We must compute true coordinates from m_PolyList + // which are relative to module position, orientation 0 + MODULE* Module = NULL; + if( PtEdge->GetParent() && (PtEdge->GetParent()->Type() == TYPE_MODULE) ) + Module = (MODULE*) PtEdge->GetParent(); + + int* ptr_base = (int*) MyMalloc( 2 * PtEdge->m_PolyPoints.size() * sizeof(int) ); + int* ptr = ptr_base; + + int* source = (int*) &PtEdge->m_PolyPoints[0]; + + for( unsigned ii = 0; ii < PtEdge->m_PolyPoints.size(); ii++ ) { - // We must compute true coordinates from m_PolyList - // which are relative to module position, orientation 0 - MODULE* Module = NULL; - if( PtEdge->GetParent() && (PtEdge->GetParent()->Type() == TYPE_MODULE) ) - Module = (MODULE*) PtEdge->GetParent(); + int x = *source++; + int y = *source++; - int* ptr_base = (int*) MyMalloc( 2 * PtEdge->m_PolyPoints.size() * sizeof(int) ); - int* ptr = ptr_base; - - int* source = (int*) &PtEdge->m_PolyPoints[0]; - - for( unsigned ii = 0; ii < PtEdge->m_PolyPoints.size(); ii++ ) + if( Module ) { - int x = *source++; - int y = *source++; - - if( Module ) - { - RotatePoint( &x, &y, Module->m_Orient ); - x += Module->m_Pos.x; - y += Module->m_Pos.y; - } - - x += PtEdge->m_Start0.x; - y += PtEdge->m_Start0.y; - - *ptr++ = x; - *ptr++ = y; + RotatePoint( &x, &y, Module->m_Orient ); + x += Module->m_Pos.x; + y += Module->m_Pos.y; } - PlotFilledPolygon( format_plot, PtEdge->m_PolyPoints.size(), ptr_base ); - free( ptr_base ); + x += PtEdge->m_Start0.x; + y += PtEdge->m_Start0.y; + + *ptr++ = x; + *ptr++ = y; } + + PlotFilledPolygon( format_plot, PtEdge->m_PolyPoints.size(), ptr_base ); + free( ptr_base ); + } break; } } @@ -582,7 +587,7 @@ void PlotTextePcb( TEXTE_PCB* pt_texte, int format_plot, int masque_layer ) switch( format_plot ) { case PLOT_FORMAT_GERBER: - SelectD_CODE_For_LineDraw(thickness); + SelectD_CODE_For_LineDraw( thickness ); break; case PLOT_FORMAT_HPGL: @@ -594,27 +599,30 @@ void PlotTextePcb( TEXTE_PCB* pt_texte, int format_plot, int masque_layer ) } PlotGraphicText( format_plot, pos, BLACK, - pt_texte->m_Text, - orient, size, - pt_texte->m_HJustify, pt_texte->m_VJustify, - thickness, pt_texte->m_Italic ); + pt_texte->m_Text, + orient, size, + pt_texte->m_HJustify, pt_texte->m_VJustify, + thickness, pt_texte->m_Italic ); } /*********************************************************/ -void PlotFilledAreas( ZONE_CONTAINER * aZone, int aFormat ) +void PlotFilledAreas( ZONE_CONTAINER* aZone, int aFormat ) /*********************************************************/ + /* Plot areas (given by .m_FilledPolysList member) in a zone -*/ + */ { static int* CornersBuffer = NULL; static unsigned CornersBufferSize = 0; - unsigned imax = aZone->m_FilledPolysList.size(); + unsigned imax = aZone->m_FilledPolysList.size(); if( imax == 0 ) // Nothing to draw 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,11 +645,21 @@ 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( aZone->m_FillMode == 0) // We are using solid polygons (if != 0: using segments in m_Zone) + 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 ) + if( aZone->m_ZoneMinThickness > 0 ) PlotPolygon( aFormat, corners_count, CornersBuffer, aZone->m_ZoneMinThickness ); corners_count = 0; ii = 0; @@ -647,6 +667,7 @@ void PlotFilledAreas( ZONE_CONTAINER * aZone, int aFormat ) } } + /******************************************************************************/ void PlotDrawSegment( DRAWSEGMENT* pt_segm, int Format, int masque_layer ) /******************************************************************************/ @@ -676,7 +697,7 @@ void PlotDrawSegment( DRAWSEGMENT* pt_segm, int Format, int masque_layer ) if( pt_segm->m_Shape == S_ARC ) { - radius = (int) hypot( (double) (end.x - start.x), (double) (end.y - start.y) ); + radius = (int) hypot( (double) (end.x - start.x), (double) (end.y - start.y) ); StAngle = ArcTangente( end.y - start.y, end.x - start.x ); EndAngle = StAngle + pt_segm->m_Angle; if( StAngle > EndAngle ) @@ -686,7 +707,7 @@ void PlotDrawSegment( DRAWSEGMENT* pt_segm, int Format, int masque_layer ) switch( Format ) { case PLOT_FORMAT_GERBER: - SelectD_CODE_For_LineDraw(thickness); + SelectD_CODE_For_LineDraw( thickness ); if( pt_segm->m_Shape == S_CIRCLE ) PlotCircle( PLOT_FORMAT_GERBER, thickness, start, radius ); else if( pt_segm->m_Shape == S_ARC ) @@ -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: @@ -726,7 +747,7 @@ void PlotCircle( int format_plot, int thickness, wxPoint centre, int radius ) switch( format_plot ) { case PLOT_FORMAT_GERBER: - SelectD_CODE_For_LineDraw(thickness); + SelectD_CODE_For_LineDraw( thickness ); PlotCircle_GERBER( centre, radius, thickness ); break; @@ -762,20 +783,44 @@ 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 ) { case PLOT_FORMAT_GERBER: - SelectD_CODE_For_LineDraw(width); + SelectD_CODE_For_LineDraw( width ); PlotPolygon_GERBER( nbpoints, coord, 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: @@ -814,9 +859,9 @@ void PlotArc( int format_plot, wxPoint centre, int start_angle, int end_angle, /* Correction pour petits cercles par rapport a l'thickness du trait */ if( radius < (thickness * 10) ) - delta = 225; /* 16 segm pour 360 deg */ + delta = 225; /* 16 segm pour 360 deg */ if( radius < (thickness * 5) ) - delta = 300; /* 12 segm pour 360 deg */ + delta = 300; /* 12 segm pour 360 deg */ if( start_angle > end_angle ) end_angle += 3600; @@ -826,8 +871,8 @@ void PlotArc( int format_plot, wxPoint centre, int start_angle, int end_angle, RotatePoint( &ox, &oy, start_angle ); - if ( format_plot == PLOT_FORMAT_GERBER ) - SelectD_CODE_For_LineDraw(thickness); + if( format_plot == PLOT_FORMAT_GERBER ) + SelectD_CODE_For_LineDraw( thickness ); delta = 120; /* un cercle sera trace en 3600/delta = 30 segments / cercle*/ for( ii = start_angle + delta; ii < end_angle; ii += delta ) @@ -840,16 +885,14 @@ void PlotArc( int format_plot, wxPoint centre, int start_angle, int end_angle, switch( format_plot ) { case PLOT_FORMAT_GERBER: - PlotGERBERLine( wxPoint( centre.x + ox, centre.y + oy ), + PlotGERBERLine( wxPoint( centre.x + ox, centre.y + oy ), wxPoint( centre.x + fx, centre.y + fy ), thickness ); 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: diff --git a/pcbnew/plothpgl.cpp b/pcbnew/plothpgl.cpp index 30eb2b34f2..4d7a0757cb 100644 --- a/pcbnew/plothpgl.cpp +++ b/pcbnew/plothpgl.cpp @@ -70,7 +70,7 @@ void WinEDA_BasePcbFrame::Genere_HPGL( const wxString& FullFileName, int Layer ) return; } - SetLocaleTo_C_standard( ); + SetLocaleTo_C_standard(); Affiche_1_Parametre( this, 0, _( "File" ), FullFileName, CYAN ); @@ -101,7 +101,7 @@ void WinEDA_BasePcbFrame::Genere_HPGL( const wxString& FullFileName, int Layer ) BoardCenter.y = (int) (BoardCenter.y * scale_y); if( g_PlotScaleOpt != 1 ) - Center = TRUE; // Echelle != 1 + Center = TRUE; // Echelle != 1 /* Calcul du cadrage */ marge = (int) (marge * SCALE_HPGL); @@ -186,7 +186,7 @@ void WinEDA_BasePcbFrame::Genere_HPGL( const wxString& FullFileName, int Layer ) /* fin */ CloseFileHPGL( dest ); - SetLocaleTo_Default( ); + SetLocaleTo_Default(); } @@ -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 ) - { - size.x = size.y = pts->m_Width; - start = pts->m_Start; - end = pts->m_End; + if( (g_TabOneLayerMask[pts->GetLayer()] & masque_layer) ) + Plot_Filled_Segment_HPGL( pts->m_Start, pts->m_End, pts->m_Width, (GRFillMode)g_Plot_Mode ); + } - 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 ); - } + /* Plot filled ares */ + for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ ) + { + ZONE_CONTAINER* zone = m_Pcb->GetArea( ii ); + if( ( ( 1 << zone->GetLayer() ) & masque_layer ) == 0 ) + continue; + PlotFilledAreas( zone, PLOT_FORMAT_HPGL ); } } +/*********************************************************************************************/ +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) + */ +{ + wxPoint center; + wxSize size; + int orient; + + if( (pen_diam >= aWidth) || (g_Plot_Mode == FILAIRE) ) /* just a line is Ok */ + { + Move_Plume_HPGL( aStart, 'U' ); + Move_Plume_HPGL( aEnd, 'D' ); + Plume_HPGL( 'U' ); + return pen_diam <= aWidth;; + } + + // 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 ); - 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 ); + RotatePoint( &cx, &cy, aOrient ); PlotArc( PLOT_FORMAT_HPGL, wxPoint( cx + pos.x, cy + pos.y ), - trace_orient + 1800, trace_orient, + -aOrient, -aOrient - 1800, + size.x / 2, pen_diam ); + cx = 0; cy = -deltaxy / 2; + RotatePoint( &cx, &cy, aOrient ); + PlotArc( PLOT_FORMAT_HPGL, wxPoint( cx + pos.x, cy + pos.y ), + -aOrient - 1800, -aOrient, size.x / 2, pen_diam ); } @@ -473,7 +481,7 @@ void trace_1_pastille_RONDE_HPGL( wxPoint pos, int diametre, int modetrace ) /* Trace 1 pastille RONDE (via,pad rond) en position pos */ { char cbuf[1024]; - int rayon, delta; + int rayon, delta; UserToDeviceCoordinate( pos ); @@ -648,8 +656,8 @@ void trace_1_pad_TRAPEZE_HPGL( wxPoint padpos, wxSize size, wxSize delta, 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 */ + 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; @@ -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' ); -}