gerbv
export-rs274x.c
Go to the documentation of this file.
1 /*
2  * gEDA - GNU Electronic Design Automation
3  * This file is a part of gerbv.
4  *
5  * Copyright (C) 2008 Julian Lamb
6  *
7  * $Id$
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
22  */
23 
30 #include "gerbv.h"
31 
32 #include <math.h>
33 #include <glib/gstdio.h>
34 
35 #include "common.h"
36 
37 #undef DPRINTF
38 #define DPRINTF(...) do { if (DEBUG) printf(__VA_ARGS__); } while (0)
39 
40 #define round(x) floor(x+0.5)
41 
42 void
43 export_rs274x_write_macro (FILE *fd, gerbv_aperture_t *currentAperture,
44  gint apertureNumber) {
45  gerbv_simplified_amacro_t *ls = currentAperture->simplified;
46 
47  /* write the macro portion first */
48  fprintf(fd, "%%AMMACRO%d*\n",apertureNumber);
49  while (ls != NULL) {
50  if (ls->type == GERBV_APTYPE_MACRO_CIRCLE) {
51  fprintf(fd, "1,%d,%f,%f,%f,%f*\n",(int) ls->parameter[CIRCLE_EXPOSURE],
52  ls->parameter[CIRCLE_DIAMETER],ls->parameter[CIRCLE_CENTER_X],
53  ls->parameter[CIRCLE_CENTER_Y],
54  ls->parameter[CIRCLE_ROTATION]);
55  }
56  else if (ls->type == GERBV_APTYPE_MACRO_OUTLINE) {
57  int pointCounter;
58  int numberOfPoints = (int) ls->parameter[OUTLINE_NUMBER_OF_POINTS];
59 
60  /* for Flatcam no new line after this 3 digits */
61  fprintf(fd, "4,%d,%d,",(int) ls->parameter[OUTLINE_EXPOSURE],
62  numberOfPoints);
63  /* add 1 point for the starting point here */
64  for (pointCounter=0; pointCounter <= numberOfPoints; pointCounter++) {
65  fprintf(fd, "%f,%f,",ls->parameter[pointCounter * 2 + OUTLINE_FIRST_X],
66  ls->parameter[pointCounter * 2 + OUTLINE_FIRST_Y]);
67  }
68  fprintf(fd, "%f*\n",ls->parameter[pointCounter * 2 + OUTLINE_FIRST_X]);
69  }
70  else if (ls->type == GERBV_APTYPE_MACRO_POLYGON) {
71  fprintf(fd, "5,%d,%d,%f,%f,%f,%f*\n",(int) ls->parameter[POLYGON_EXPOSURE],
72  (int) ls->parameter[POLYGON_NUMBER_OF_POINTS],
73  ls->parameter[POLYGON_CENTER_X],ls->parameter[POLYGON_CENTER_Y],
74  ls->parameter[POLYGON_DIAMETER],ls->parameter[POLYGON_ROTATION]);
75  }
76  else if (ls->type == GERBV_APTYPE_MACRO_MOIRE) {
77  fprintf(fd, "6,%f,%f,%f,%f,%f,%d,%f,%f,%f*\n",ls->parameter[MOIRE_CENTER_X],
78  ls->parameter[MOIRE_CENTER_Y],ls->parameter[MOIRE_OUTSIDE_DIAMETER],
79  ls->parameter[MOIRE_CIRCLE_THICKNESS],ls->parameter[MOIRE_GAP_WIDTH],
80  (int) ls->parameter[MOIRE_NUMBER_OF_CIRCLES],ls->parameter[MOIRE_CROSSHAIR_THICKNESS],
81  ls->parameter[MOIRE_CROSSHAIR_LENGTH],ls->parameter[MOIRE_ROTATION]);
82  }
83  else if (ls->type == GERBV_APTYPE_MACRO_THERMAL) {
84  fprintf(fd, "7,%f,%f,%f,%f,%f,%f*\n",ls->parameter[THERMAL_CENTER_X],
85  ls->parameter[THERMAL_CENTER_Y],ls->parameter[THERMAL_OUTSIDE_DIAMETER],
86  ls->parameter[THERMAL_INSIDE_DIAMETER],ls->parameter[THERMAL_CROSSHAIR_THICKNESS],
87  ls->parameter[THERMAL_ROTATION]);
88  }
89  else if (ls->type == GERBV_APTYPE_MACRO_LINE20) {
90  fprintf(fd, "20,%d,%f,%f,%f,%f,%f,%f*\n",(int) ls->parameter[LINE20_EXPOSURE],
91  ls->parameter[LINE20_LINE_WIDTH],ls->parameter[LINE20_START_X],
92  ls->parameter[LINE20_START_Y],ls->parameter[LINE20_END_X],
93  ls->parameter[LINE20_END_Y],ls->parameter[LINE20_ROTATION]);
94  }
95  else if (ls->type == GERBV_APTYPE_MACRO_LINE21) {
96  fprintf(fd, "21,%d,%f,%f,%f,%f,%f*\n",(int) ls->parameter[LINE21_EXPOSURE],
97  ls->parameter[LINE21_WIDTH],ls->parameter[LINE21_HEIGHT],
98  ls->parameter[LINE21_CENTER_X],ls->parameter[LINE21_CENTER_Y],
99  ls->parameter[LINE21_ROTATION]);
100  }
101  else if (ls->type == GERBV_APTYPE_MACRO_LINE22) {
102  fprintf(fd, "22,%d,%f,%f,%f,%f,%f*\n",(int) ls->parameter[LINE22_EXPOSURE],
103  ls->parameter[LINE22_WIDTH],ls->parameter[LINE22_HEIGHT],
104  ls->parameter[LINE22_LOWER_LEFT_X],ls->parameter[LINE22_LOWER_LEFT_Y],
105  ls->parameter[LINE22_ROTATION]);
106  }
107  ls = ls->next;
108  }
109  fprintf(fd, "%%\n");
110  /* and finally create an aperture definition to use the macro */
111  fprintf(fd, "%%ADD%dMACRO%d*%%\n",apertureNumber,apertureNumber);
112 }
113 
114 void
115 export_rs274x_write_apertures (FILE *fd, gerbv_image_t *image) {
116  gerbv_aperture_t *currentAperture;
117  gint numberOfRequiredParameters=0,numberOfOptionalParameters=0,i,j;
118 
119  /* the image should already have been cleaned by a duplicate_image call, so we can safely
120  assume the aperture range is correct */
121  for (i=APERTURE_MIN; i<APERTURE_MAX; i++) {
122  gboolean writeAperture=TRUE;
123 
124  currentAperture = image->aperture[i];
125 
126  if (!currentAperture)
127  continue;
128 
129  switch (currentAperture->type) {
130  case GERBV_APTYPE_CIRCLE:
131  fprintf(fd, "%%ADD%d",i);
132  fprintf(fd, "C,");
133  numberOfRequiredParameters = 1;
134  numberOfOptionalParameters = 2;
135  break;
137  fprintf(fd, "%%ADD%d",i);
138  fprintf(fd, "R,");
139  numberOfRequiredParameters = 2;
140  numberOfOptionalParameters = 2;
141  break;
142  case GERBV_APTYPE_OVAL:
143  fprintf(fd, "%%ADD%d",i);
144  fprintf(fd, "O,");
145  numberOfRequiredParameters = 2;
146  numberOfOptionalParameters = 2;
147  break;
149  fprintf(fd, "%%ADD%d",i);
150  fprintf(fd, "P,");
151  numberOfRequiredParameters = 2;
152  numberOfOptionalParameters = 3;
153  break;
154  case GERBV_APTYPE_MACRO:
155  export_rs274x_write_macro (fd, currentAperture, i);
156  writeAperture=FALSE;
157  break;
158  default:
159  writeAperture=FALSE;
160  break;
161  }
162  if (writeAperture) {
163  /* write the parameter list */
164  for (j=0; j<(numberOfRequiredParameters + numberOfOptionalParameters); j++) {
165  if ((j < numberOfRequiredParameters) || (currentAperture->parameter[j] != 0)) {
166  /* print the "X" character to separate the parameters */
167  if (j>0)
168  fprintf(fd, "X");
169  fprintf(fd, "%.4f",currentAperture->parameter[j]);
170  }
171  }
172  fprintf(fd, "*%%\n");
173  }
174  }
175 }
176 
177 void
178 export_rs274x_write_layer_change (gerbv_layer_t *oldLayer, gerbv_layer_t *newLayer, FILE *fd) {
179  if (oldLayer->polarity != newLayer->polarity) {
180  /* polarity changed */
181  if (newLayer->polarity == GERBV_POLARITY_CLEAR) {
182  fprintf(fd, "%%LPC*%%\n");
183  } else {
184  fprintf(fd, "%%LPD*%%\n");
185  }
186  }
187 }
188 
189 void
190 export_rs274x_write_state_change (gerbv_netstate_t *oldState, gerbv_netstate_t *newState, FILE *fd) {
191 
192 
193 }
194 
195 gboolean
196 gerbv_export_rs274x_file_from_image (const gchar *filename, gerbv_image_t *inputImage,
197  gerbv_user_transformation_t *transform)
198 {
199  const double decimal_coeff = 1e6;
200  FILE *fd;
201  gerbv_netstate_t *oldState;
202  gerbv_layer_t *oldLayer;
203  gboolean insidePolygon=FALSE;
204  gerbv_user_transformation_t *thisTransform;
205 
206  // force gerbv to output decimals as dots (not commas for other locales)
207  setlocale(LC_NUMERIC, "C");
208 
209  if (transform != NULL) {
210  thisTransform = transform;
211  } else {
212  static gerbv_user_transformation_t identityTransform =
213  {0,0,1,1,0,FALSE,FALSE,FALSE};
214  thisTransform = &identityTransform;
215  }
216  if ((fd = g_fopen(filename, "w")) == NULL) {
217  GERB_COMPILE_ERROR(_("Can't open file for writing: %s"),
218  filename);
219  return FALSE;
220  }
221 
222  /* duplicate the image, cleaning it in the process */
223  gerbv_image_t *image = gerbv_image_duplicate_image (inputImage, thisTransform);
224 
225  /* write header info */
226  fprintf(fd, "G04 This is an RS-274x file exported by *\n");
227  fprintf(fd, "G04 gerbv version %s *\n",VERSION);
228  fprintf(fd, "G04 More information is available about gerbv at *\n");
229  fprintf(fd, "G04 https://gerbv.github.io/ *\n");
230  fprintf(fd, "G04 --End of header info--*\n");
231  fprintf(fd, "%%MOIN*%%\n");
232  fprintf(fd, "%%FSLAX36Y36*%%\n");
233 
234  /* check the image info struct for any non-default settings */
235  /* image offset */
236  if ((image->info->offsetA > 0.0) || (image->info->offsetB > 0.0))
237  fprintf(fd, "%%IOA%fB%f*%%\n",image->info->offsetA,image->info->offsetB);
238  /* image polarity */
239  if (image->info->polarity == GERBV_POLARITY_CLEAR)
240  fprintf(fd, "%%IPNEG*%%\n");
241  else
242  fprintf(fd, "%%IPPOS*%%\n");
243  /* image name */
244  if (image->info->name)
245  fprintf(fd, "%%IN%s*%%\n",image->info->name);
246  /* plotter film */
247  if (image->info->plotterFilm)
248  fprintf(fd, "%%PF%s*%%\n",image->info->plotterFilm);
249 
250  /* image rotation */
251  if ((image->info->imageRotation != 0.0)
252  || (thisTransform->rotation != 0.0))
253  fprintf(fd, "%%IR%d*%%\n",
254  (int)round(RAD2DEG(image->info->imageRotation))%360);
255 
256  if ((image->info->imageJustifyTypeA != GERBV_JUSTIFY_NOJUSTIFY)
257  || (image->info->imageJustifyTypeB != GERBV_JUSTIFY_NOJUSTIFY)) {
258  fprintf(fd, "%%IJA");
259  if (image->info->imageJustifyTypeA == GERBV_JUSTIFY_CENTERJUSTIFY)
260  fprintf(fd, "C");
261  else
262  fprintf(fd, "%.4f",image->info->imageJustifyOffsetA);
263  fprintf(fd, "B");
264  if (image->info->imageJustifyTypeB == GERBV_JUSTIFY_CENTERJUSTIFY)
265  fprintf(fd, "C");
266  else
267  fprintf(fd, "%.4f",image->info->imageJustifyOffsetB);
268  fprintf(fd, "*%%\n");
269 
270  }
271  /* handle scale user orientation transforms */
272  if (fabs(thisTransform->scaleX - 1) > GERBV_PRECISION_LINEAR_INCH
273  || fabs(thisTransform->scaleY - 1) > GERBV_PRECISION_LINEAR_INCH) {
274  fprintf(fd, "%%SFA%.4fB%.4f*%%\n",thisTransform->scaleX,thisTransform->scaleY);
275  }
276  /* handle mirror image user orientation transform */
277  if ((thisTransform->mirrorAroundX)||(thisTransform->mirrorAroundY)) {
278  fprintf(fd, "%%MIA%dB%d*%%\n",thisTransform->mirrorAroundY,thisTransform->mirrorAroundX);
279  }
280 
281  /* define all apertures */
282  fprintf(fd, "G04 --Define apertures--*\n");
283  export_rs274x_write_apertures (fd, image);
284 
285  /* write rest of image */
286  fprintf(fd, "G04 --Start main section--*\n");
287  gint currentAperture = 0;
288  gerbv_net_t *currentNet;
289 
290  oldLayer = image->layers;
291  oldState = image->states;
292  /* skip the first net, since it's always zero due to the way we parse things */
293  for (currentNet = image->netlist->next; currentNet; currentNet = currentNet->next){
294  /* check for "layer" changes (RS274X commands) */
295  if (currentNet->layer != oldLayer)
296  export_rs274x_write_layer_change (oldLayer, currentNet->layer, fd);
297 
298  /* check for new "netstate" (more RS274X commands) */
299  if (currentNet->state != oldState)
300  export_rs274x_write_state_change (oldState, currentNet->state, fd);
301 
302  /* check for tool changes */
303  /* also, make sure the aperture number is a valid one, since sometimes
304  the loaded file may refer to invalid apertures */
305  if ((currentNet->aperture != currentAperture)&&
306  (image->aperture[currentNet->aperture] != NULL)) {
307  fprintf(fd, "G54D%02d*\n",currentNet->aperture);
308  currentAperture = currentNet->aperture;
309  }
310 
311  oldLayer = currentNet->layer;
312  oldState = currentNet->state;
313 
314  long xVal,yVal,endX,endY,centerX,centerY;
315  switch (currentNet->interpolation) {
320  /* see if we need to write an "aperture off" line to get
321  the pen to the right start point */
322  if ((!insidePolygon) && (currentNet->aperture_state == GERBV_APERTURE_STATE_ON)) {
323  xVal = (long) round(currentNet->start_x * decimal_coeff);
324  yVal = (long) round(currentNet->start_y * decimal_coeff);
325  fprintf(fd, "G01X%07ldY%07ldD02*\n",xVal,yVal);
326  }
327  xVal = (long) round(currentNet->stop_x * decimal_coeff);
328  yVal = (long) round(currentNet->stop_y * decimal_coeff);
329  fprintf(fd, "G01X%07ldY%07ld",xVal,yVal);
330  /* and finally, write the esposure value */
331  if (currentNet->aperture_state == GERBV_APERTURE_STATE_OFF)
332  fprintf(fd, "D02*\n");
333  else if (currentNet->aperture_state == GERBV_APERTURE_STATE_ON)
334  fprintf(fd, "D01*\n");
335  else
336  fprintf(fd, "D03*\n");
337  break;
340  /* see if we need to write an "aperture off" line to get
341  the pen to the right start point */
342  if ((!insidePolygon) && (currentNet->aperture_state == GERBV_APERTURE_STATE_ON)) {
343  xVal = (long) round(currentNet->start_x * decimal_coeff);
344  yVal = (long) round(currentNet->start_y * decimal_coeff);
345  fprintf(fd, "G01X%07ldY%07ldD02*\n",xVal,yVal);
346  }
347  centerX= (long) round((currentNet->cirseg->cp_x - currentNet->start_x) * decimal_coeff);
348  centerY= (long) round((currentNet->cirseg->cp_y - currentNet->start_y) * decimal_coeff);
349  endX = (long) round(currentNet->stop_x * decimal_coeff);
350  endY = (long) round(currentNet->stop_y * decimal_coeff);
351 
352  /* always use multi-quadrant, since it's much easier to export */
353  /* and most all software should support it */
354  fprintf(fd, "G75*\n");
355 
357  fprintf(fd, "G02"); /* Clockwise */
358  else
359  fprintf(fd, "G03"); /* Counter clockwise */
360 
361  /* don't write the I and J values if the exposure is off */
362  if (currentNet->aperture_state == GERBV_APERTURE_STATE_ON)
363  fprintf(fd, "X%07ldY%07ldI%07ldJ%07ld",endX,endY,centerX,centerY);
364  else
365  fprintf(fd, "X%07ldY%07ld",endX,endY);
366  /* and finally, write the esposure value */
367  if (currentNet->aperture_state == GERBV_APERTURE_STATE_OFF)
368  fprintf(fd, "D02*\n");
369  else if (currentNet->aperture_state == GERBV_APERTURE_STATE_ON)
370  fprintf(fd, "D01*\n");
371  else
372  fprintf(fd, "D03*\n");
373  break;
375  fprintf(fd, "G36*\n");
376  insidePolygon = TRUE;
377  break;
379  fprintf(fd, "G37*\n");
380  insidePolygon = FALSE;
381  break;
382  default:
383  break;
384  }
385  }
386 
387  fprintf(fd, "M02*\n");
388 
389  gerbv_destroy_image (image);
390  fclose(fd);
391 
392  // return to the default locale
393  setlocale(LC_NUMERIC, "");
394  return TRUE;
395 }
gboolean gerbv_export_rs274x_file_from_image(const gchar *filename, gerbv_image_t *inputImage, gerbv_user_transformation_t *transform)
Export an image to a new file in RS274X format.
void gerbv_destroy_image(gerbv_image_t *image)
Free an image structure.
Definition: gerb_image.c:106
gerbv_image_t * gerbv_image_duplicate_image(gerbv_image_t *sourceImage, gerbv_user_transformation_t *transform)
Duplicate an existing image and return the new copy.
Definition: gerb_image.c:920
The main header file for the libgerbv library.
@ GERBV_APERTURE_STATE_OFF
Definition: gerbv.h:178
@ GERBV_APERTURE_STATE_ON
Definition: gerbv.h:179
@ GERBV_POLARITY_CLEAR
Definition: gerbv.h:284
@ GERBV_APTYPE_MACRO_LINE20
Definition: gerbv.h:170
@ GERBV_APTYPE_MACRO_LINE21
Definition: gerbv.h:171
@ GERBV_APTYPE_OVAL
Definition: gerbv.h:162
@ GERBV_APTYPE_MACRO_OUTLINE
Definition: gerbv.h:166
@ GERBV_APTYPE_MACRO_CIRCLE
Definition: gerbv.h:165
@ GERBV_APTYPE_MACRO
Definition: gerbv.h:164
@ GERBV_APTYPE_CIRCLE
Definition: gerbv.h:160
@ GERBV_APTYPE_POLYGON
Definition: gerbv.h:163
@ GERBV_APTYPE_MACRO_POLYGON
Definition: gerbv.h:167
@ GERBV_APTYPE_RECTANGLE
Definition: gerbv.h:161
@ GERBV_APTYPE_MACRO_THERMAL
Definition: gerbv.h:169
@ GERBV_APTYPE_MACRO_LINE22
Definition: gerbv.h:172
@ GERBV_APTYPE_MACRO_MOIRE
Definition: gerbv.h:168
@ GERBV_INTERPOLATION_LINEARx01
Definition: gerbv.h:304
@ GERBV_INTERPOLATION_PAREA_START
Definition: gerbv.h:308
@ GERBV_INTERPOLATION_LINEARx001
Definition: gerbv.h:305
@ GERBV_INTERPOLATION_CW_CIRCULAR
Definition: gerbv.h:306
@ GERBV_INTERPOLATION_PAREA_END
Definition: gerbv.h:309
@ GERBV_INTERPOLATION_LINEARx10
Definition: gerbv.h:303
@ GERBV_INTERPOLATION_CCW_CIRCULAR
Definition: gerbv.h:307
@ GERBV_INTERPOLATION_LINEARx1
Definition: gerbv.h:302
gerbv_layer_t * layers
Definition: gerbv.h:724
gerbv_net_t * netlist
Definition: gerbv.h:729
gerbv_aperture_t * aperture[APERTURE_MAX]
Definition: gerbv.h:723
gerbv_netstate_t * states
Definition: gerbv.h:725
gerbv_image_info_t * info
Definition: gerbv.h:728
gerbv_polarity_t polarity
Definition: gerbv.h:638
gerbv_layer_t * layer
Definition: gerbv.h:668
double stop_y
Definition: gerbv.h:660
gerbv_aperture_state_t aperture_state
Definition: gerbv.h:663
double stop_x
Definition: gerbv.h:659
double start_x
Definition: gerbv.h:657
gerbv_netstate_t * state
Definition: gerbv.h:669
struct gerbv_net * next
Definition: gerbv.h:666
double start_y
Definition: gerbv.h:658
gerbv_interpolation_t interpolation
Definition: gerbv.h:664
gerbv_cirseg_t * cirseg
Definition: gerbv.h:665
int aperture
Definition: gerbv.h:662