kicad/pcbnew/gen_modules_placefile.cpp

428 lines
12 KiB
C++

/*************************************/
/* fichier gen_modules_placefile.cpp */
/*************************************/
/*
1 - create ascii files for automatic placement of smd components
2 - create a module report (pos and module descr) (ascii file)
*/
#include "fctsys.h"
#include "common.h"
#include "pcbnew.h"
#include "trigo.h"
class LIST_MOD /* Permet de lister les elements utiles des modules */
{
public:
MODULE * m_Module;
const wxChar * m_Reference;
const wxChar * m_Value;
};
/* variables locale : */
static wxPoint File_Place_Offset; /* Offset des coord de placement pour le fichier généré */
/* Routines Locales */
static void WriteDrawSegmentPcb(DRAWSEGMENT * PtDrawSegment, FILE * rptfile);
/* Routine de tri utilisee par GenereModulesPosition() */
static int ListeModCmp(LIST_MOD * Ref, LIST_MOD * Cmp)
{
return ( StrLenNumCmp(Ref->m_Reference, Cmp->m_Reference, 16) );
}
/**************************************************************/
void WinEDA_PcbFrame::GenModulesPosition(wxCommandEvent& event)
/**************************************************************/
/* Routine de generation du fichier de positionnement des modules,
utilisé pour les machines de placement de composants
*/
{
float conv_unit;
int NbMod, ii;
bool GenCu = FALSE;
MODULE * Module;
LIST_MOD * Liste;
char Line[1024], Buff[80];
wxString NameLayerCu, NameLayerCmp, msg;
FILE * LayerCu = NULL, *LayerCmp = NULL;
/* Calcul des echelles de conversion */
conv_unit = 0.0001; /* unites = INCHES */
// if(IF_DRILL_METRIC) conv_unit = 0.000254; /* unites = mm */
File_Place_Offset = m_Auxiliary_Axis_Position;
/* Calcul du nombre de modules utiles ( Attribut CMS, non VIRTUAL ) ) */
NbMod = 0; Module = m_Pcb->m_Modules;
for ( ; Module != NULL; Module = (MODULE*) Module->Pnext)
{
if( Module->m_Attributs & MOD_VIRTUAL ) continue;
if( (Module->m_Attributs & MOD_CMS) == 0 ) continue;
if( Module->m_Layer == CUIVRE_N) GenCu = TRUE;
NbMod++;
}
if ( NbMod == 0 )
{
DisplayError(this, _("No Modules for Automated Placement"), 20); return;
}
/* Init nom fichier */
NameLayerCmp = m_CurrentScreen->m_FileName;
ChangeFileNameExt(NameLayerCmp, wxT("-cmp.pos"));
LayerCmp = wxFopen(NameLayerCmp, wxT("wt"));
if (LayerCmp == 0)
{
msg = _("Unable to create ") + NameLayerCu;
DisplayError(this, msg); return ;
}
if( GenCu )
{
NameLayerCu = m_CurrentScreen->m_FileName;
ChangeFileNameExt(NameLayerCu, wxT("-copper.pos"));
LayerCu = wxFopen(NameLayerCu, wxT("wt"));
if (LayerCu == 0)
{
msg = _("Unable to create ") + NameLayerCu;
DisplayError(this, msg);
fclose(LayerCmp);
return ;
}
}
// Switch the locale to standard C (needed to print floating point numbers like 1.3)
setlocale(LC_NUMERIC, "C");
/* Affichage du bilan : */
MsgPanel->EraseMsgBox();
Affiche_1_Parametre(this,0,_("Component side place file:"),NameLayerCmp,BLUE);
if( GenCu )
Affiche_1_Parametre(this,32,_("Copper side place file:"),NameLayerCu,BLUE);
msg.Empty(); msg << NbMod;
Affiche_1_Parametre(this,65, _("Module count"), msg, RED);
/* Etablissement de la liste des modules par ordre alphabetique */
Liste = (LIST_MOD*) MyZMalloc( NbMod * sizeof(LIST_MOD) );
Module = (MODULE*)m_Pcb->m_Modules;
for( ii = 0; Module != NULL; Module = Module->Next() )
{
if( Module->m_Attributs & MOD_VIRTUAL ) continue;
if( (Module->m_Attributs & MOD_CMS) == 0 ) continue;
Liste[ii].m_Module = Module;
Liste[ii].m_Reference = Module->m_Reference->m_Text;
Liste[ii].m_Value = Module->m_Value->m_Text;
ii++;
}
qsort(Liste, NbMod , sizeof(LIST_MOD),
(int(*)(const void *, const void*))ListeModCmp);
/* Generation entete du fichier 'commentaires) */
sprintf(Line,"### Module positions - created on %s ###\n",
DateAndTime(Buff) );
fputs(Line,LayerCmp);
if( GenCu ) fputs(Line,LayerCu);
wxString Title = g_Main_Title + wxT(" ") + GetBuildVersion();
sprintf(Line,"### Printed by PcbNew version %s\n", CONV_TO_UTF8(Title) );
fputs(Line,LayerCmp);
if( GenCu ) fputs(Line,LayerCu);
sprintf(Line,"## Unit = inches, Angle = deg.\n");
fputs(Line,LayerCmp);
if( GenCu ) fputs(Line,LayerCu);
sprintf(Line,"## Side : Components\n");
fputs(Line,LayerCmp);
if( GenCu )
{
sprintf(Line,"## Side : Copper\n");
fputs(Line,LayerCu);
}
sprintf(Line,
"# Ref Val PosX PosY Rot Side\n");
fputs(Line,LayerCmp);
if( GenCu ) fputs(Line,LayerCu);
/* Generation lignes utiles du fichier */
for ( ii = 0 ; ii < NbMod; ii++)
{
wxPoint module_pos;
wxString ref = Liste[ii].m_Reference;
wxString val = Liste[ii].m_Value;
sprintf(Line,"%-8.8s %-16.16s ", CONV_TO_UTF8(ref), CONV_TO_UTF8(val) );
module_pos = Liste[ii].m_Module->m_Pos;
module_pos.x -= File_Place_Offset.x;
module_pos.y -= File_Place_Offset.y;
char * text = Line + strlen(Line);
sprintf( text, " %9.4f %9.4f %8.1f ",
(float) module_pos.x * conv_unit,
(float) module_pos.y * conv_unit,
(float) Liste[ii].m_Module->m_Orient / 10);
if (Liste[ii].m_Module->m_Layer == CMP_N)
{
strcat(Line,"Cmp.\n");
fputs(Line, LayerCmp);
}
else if (Liste[ii].m_Module->m_Layer == CUIVRE_N)
{
strcat(Line,"Cu\n");
fputs(Line, LayerCu);
}
}
/* Generation fin du fichier */
fputs("## End\n", LayerCmp);
fclose(LayerCmp);
if( GenCu )
{
fputs("## End\n", LayerCu);
fclose(LayerCu);
}
MyFree(Liste);
setlocale(LC_NUMERIC, ""); // revert to the current locale
msg = wxT("Cmp File: ") + NameLayerCmp;
if( GenCu ) msg += wxT("\nCu File: ") + NameLayerCu;
DisplayInfo(this, msg);
}
/**************************************************************/
void WinEDA_PcbFrame::GenModuleReport(wxCommandEvent& event)
/**************************************************************/
/* Print a module report.
*/
{
float conv_unit;
MODULE * Module;
D_PAD * pad;
char Line[1024], Buff[80];
wxString FullFileName, NameLayerCmp, msg;
FILE * rptfile;
wxPoint module_pos;
/* Calcul des echelles de conversion */
conv_unit = 0.0001; /* unites = INCHES */
// if(IF_DRILL_METRIC) conv_unit = 0.000254; /* unites = mm */
File_Place_Offset = wxPoint(0,0);
/* Init nom fichier */
FullFileName = m_CurrentScreen->m_FileName;
ChangeFileNameExt(FullFileName, wxT(".rpt"));
rptfile = wxFopen(FullFileName, wxT("wt"));
if (rptfile == NULL)
{
msg = _("Unable to create ") + FullFileName;
DisplayError(this, msg); return ;
}
// Switch the locale to standard C (needed to print floating point numbers like 1.3)
setlocale(LC_NUMERIC, "C");
/* Generation entete du fichier 'commentaires) */
sprintf(Line,"## Module report - date %s\n", DateAndTime(Buff) );
fputs(Line,rptfile);
wxString Title = g_Main_Title + wxT(" ") + GetBuildVersion();
sprintf(Line,"## Created by PcbNew version %s\n", CONV_TO_UTF8(Title) );
fputs(Line,rptfile);
fputs("## Unit = inches, Angle = deg.\n",rptfile);
/* Generation lignes utiles du fichier */
fputs("##\n", rptfile);
fputs("\n$BeginDESCRIPTION\n", rptfile);
m_Pcb->ComputeBoundaryBox();
fputs("\n$BOARD\n", rptfile);
fputs("unit INCH\n", rptfile);
sprintf(Line,"upper_left_corner %9.6f %9.6f\n",
(float) m_Pcb->m_BoundaryBox.GetX() * conv_unit,
(float) m_Pcb->m_BoundaryBox.GetY() * conv_unit);
fputs(Line, rptfile);
sprintf(Line,"lower_right_corner %9.6f %9.6f\n",
(float) (m_Pcb->m_BoundaryBox.GetRight() ) * conv_unit,
(float) (m_Pcb->m_BoundaryBox.GetBottom() ) * conv_unit);
fputs(Line, rptfile);
fputs("$EndBOARD\n\n", rptfile);
Module = (MODULE*)m_Pcb->m_Modules;
for( ; Module != NULL; Module = Module->Next() )
{
sprintf(Line,"$MODULE \"%s\"\n", CONV_TO_UTF8(Module->m_Reference->m_Text));
fputs(Line, rptfile);
sprintf(Line,"reference \"%s\"\n", CONV_TO_UTF8(Module->m_Reference->m_Text));
fputs(Line, rptfile);
sprintf(Line,"value \"%s\"\n", CONV_TO_UTF8(Module->m_Value->m_Text));
fputs(Line, rptfile);
sprintf(Line,"footprint \"%s\"\n", CONV_TO_UTF8(Module->m_LibRef));
fputs(Line, rptfile);
msg = wxT("attribut");
if ( Module->m_Attributs & MOD_VIRTUAL ) msg += wxT(" virtual");
if ( Module->m_Attributs & MOD_CMS ) msg += wxT(" smd");
if ( (Module->m_Attributs & (MOD_VIRTUAL|MOD_CMS)) == 0 )
msg += wxT(" none");
msg += wxT("\n");
fputs(CONV_TO_UTF8(msg), rptfile);
module_pos = Module->m_Pos;
module_pos.x -= File_Place_Offset.x;
module_pos.y -= File_Place_Offset.y;
sprintf( Line, "position %9.6f %9.6f\n",
(float) module_pos.x * conv_unit,
(float) module_pos.y * conv_unit);
fputs(Line, rptfile);
sprintf( Line, "orientation %.2f\n", (float) Module->m_Orient / 10);
if (Module->m_Layer == CMP_N) strcat(Line,"layer component\n");
else if (Module->m_Layer == CUIVRE_N) strcat(Line,"layer copper\n");
else strcat(Line,"layer other\n");
fputs(Line, rptfile);
Module->Write_3D_Descr( rptfile );
for ( pad = Module->m_Pads; pad != NULL; pad = pad->Next() )
{
fprintf( rptfile,"$PAD \"%.4s\"\n", pad->m_Padname);
sprintf( Line, "position %9.6f %9.6f\n",
(float) pad->m_Pos0.x * conv_unit,
(float) pad->m_Pos0.y * conv_unit);
fputs(Line, rptfile);
sprintf( Line, "size %9.6f %9.6f\n",
(float) pad->m_Size.x * conv_unit,
(float) pad->m_Size.y * conv_unit);
fputs(Line, rptfile);
sprintf( Line, "drill %9.6f\n", (float) pad->m_Drill.x * conv_unit);
fputs(Line, rptfile);
sprintf( Line, "shape_offset %9.6f %9.6f\n",
(float) pad->m_Offset.x * conv_unit,
(float) pad->m_Offset.y * conv_unit);
fputs(Line, rptfile);
sprintf( Line, "orientation %.2f\n", (float) (pad->m_Orient - Module->m_Orient) / 10);
fputs(Line, rptfile);
char *shape_name[6] = {"??? ","Circ","Rect","Oval","trap","spec"} ;
sprintf( Line, "Shape %s\n", shape_name[pad->m_PadShape]);
fputs(Line, rptfile);
int layer = 0;
if(pad->m_Masque_Layer & CUIVRE_LAYER) layer = 1;
if(pad->m_Masque_Layer & CMP_LAYER) layer |= 2;
char *layer_name[4] = {"??? ","copper","component","all"} ;
sprintf( Line, "Layer %s\n", layer_name[layer]);
fputs(Line, rptfile);
fprintf( rptfile,"$EndPAD\n");
}
fprintf( rptfile,"$EndMODULE %s\n\n", Module->m_Reference->m_Text.GetData());
}
/* Write board Edges */
EDA_BaseStruct * PtStruct;
for ( PtStruct = m_Pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Pnext)
{
if( PtStruct->m_StructType != TYPEDRAWSEGMENT ) continue;
if( ((DRAWSEGMENT *) PtStruct)->m_Layer != EDGE_N ) continue;
WriteDrawSegmentPcb( (DRAWSEGMENT *) PtStruct, rptfile);
}
/* Generation fin du fichier */
fputs("$EndDESCRIPTION\n", rptfile);
fclose(rptfile);
setlocale(LC_NUMERIC, ""); // revert to the current locale
}
/*******************************************************************/
void WriteDrawSegmentPcb(DRAWSEGMENT * PtDrawSegment, FILE * rptfile)
/*******************************************************************/
/* Sortie dsur rptfile d'un segment type drawing PCB:
Les contours sont de differents type:
segment
cercle
arc
*/
{
double conv_unit, ux0, uy0, dx, dy;
double rayon, width;
char Line[1024];
/* Calcul des echelles de conversion */
conv_unit = 0.0001; /* unites = INCHES */
/* coord de depart */
ux0 = PtDrawSegment->m_Start.x * conv_unit;
uy0 = PtDrawSegment->m_Start.y * conv_unit;
/* coord d'arrivee */
dx = PtDrawSegment->m_End.x * conv_unit;
dy = PtDrawSegment->m_End.y * conv_unit;
width = PtDrawSegment->m_Width * conv_unit;
switch (PtDrawSegment->m_Shape)
{
case S_CIRCLE:
rayon = hypot(dx-ux0,dy-uy0);
sprintf(Line,"$CIRCLE \n"); fputs(Line, rptfile);
sprintf( Line, "centre %.6lf %.6lf\n", ux0, uy0);
sprintf( Line, "radius %.6lf\n", rayon);
sprintf( Line, "width %.6lf\n", width);
sprintf(Line,"$EndCIRCLE \n");
fputs(Line, rptfile);
break;
case S_ARC:
{
int endx = PtDrawSegment->m_End.x, endy = PtDrawSegment->m_End.y;
rayon = hypot(dx-ux0,dy-uy0);
RotatePoint(&endx, &endy, PtDrawSegment->m_Start.x, PtDrawSegment->m_Start.y,PtDrawSegment->m_Angle);
sprintf(Line,"$ARC \n"); fputs(Line, rptfile);
sprintf( Line, "centre %.6lf %.6lf\n", ux0, uy0);
sprintf( Line, "start %.6lf %.6lf\n", endx * conv_unit, endy * conv_unit);
sprintf( Line, "end %.6lf %.6lf\n", dx, dy);
sprintf( Line, "width %.6lf\n", width);
sprintf(Line,"$EndARC \n");
fputs(Line, rptfile);
}
break;
default:
sprintf(Line,"$LINE \n");
fputs(Line, rptfile);
sprintf( Line, "start %.6lf %.6lf\n", ux0, uy0);
sprintf( Line, "end %.6lf %.6lf\n", dx, dy);
sprintf( Line, "width %.6lf\n", width);
sprintf(Line,"$EndLINE \n");
fputs(Line, rptfile);
break;
}
}