40 void gerb_transf_free(gerbv_transf_t *transf)
46 void gerb_transf_reset(gerbv_transf_t* transf)
48 memset(transf,0,
sizeof(gerbv_transf_t));
50 transf->r_mat[0][0] = transf->r_mat[1][1] = 1.0;
58 gerbv_transf_t* gerb_transf_new(
void)
60 gerbv_transf_t *transf;
62 transf = g_malloc(
sizeof(gerbv_transf_t));
63 gerb_transf_reset(transf);
78 double s = sin(angle), c = cos(angle);
80 memcpy(m, transf->r_mat,
sizeof(m));
81 transf->r_mat[0][0] = c * m[0][0] - s * m[1][0];
82 transf->r_mat[0][1] = c * m[0][1] - s * m[1][1];
83 transf->r_mat[1][0] = s * m[0][0] + c * m[1][0];
84 transf->r_mat[1][1] = s * m[0][1] + c * m[1][1];
98 transf->offset[0] += shift_x;
99 transf->offset[1] += shift_y;
103 void gerb_transf_apply(
double x,
double y, gerbv_transf_t* transf,
double *out_x,
double *out_y)
108 *out_x = (x * transf->r_mat[0][0] + y * transf->r_mat[0][1]) * transf->scale;
109 *out_y = (x * transf->r_mat[1][0] + y * transf->r_mat[1][1]) * transf->scale;
110 *out_x += transf->offset[0];
111 *out_y += transf->offset[1];
117 pick_and_place_reset_bounding_box (
gerbv_net_t *net) {
132 sscanf(str,
"%lf %40s", &x, unit);
133 if(strstr(unit,
"in")) {
135 }
else if(strstr(unit,
"cm")) {
137 }
else if(strstr(unit,
"mm")) {
153 char delimiter[4] =
"|,;:";
155 int idx, idx_max = 0;
157 memset(counter, 0,
sizeof(counter));
158 for(ptr = str; *ptr; ptr++) {
177 if(counter[idx] > counter[idx_max]) {
182 if (counter[idx_max] > n) {
183 return (
unsigned char) delimiter[idx_max];
199 PnpPartData pnpPartData;
200 int lineCounter = 0, parsedLines = 0;
203 char buf[MAXL+2], buf0[MAXL+2];
205 gerbv_transf_t *tr_rot = gerb_transf_new();
206 GArray *pnpParseDataArray = g_array_new (FALSE, FALSE,
sizeof(PnpPartData));
207 gboolean foundValidDataRow = FALSE;
213 setlocale(LC_NUMERIC,
"C" );
215 while ( fgets(buf, MAXL, fd->fd) != NULL ) {
216 int len = strlen(buf)-1;
217 int i_length = 0, i_width = 0;
220 if(lineCounter < 2) {
227 if(len >= 0 && buf[len] ==
'\n') {
230 if(len >= 0 && buf[len] ==
'\r') {
237 if ((len > 0) && (buf[0] ==
'%')) {
242 if ((len > 4) && (strncmp(buf,
"G54 ", 4) == 0)) {
243 g_array_free (pnpParseDataArray, TRUE);
248 if ((len > 4) && (strncmp(buf,
"G04 ", 4) == 0)) {
249 g_array_free (pnpParseDataArray, TRUE);
260 ret = csv_row_parse(buf, MAXL, buf0, MAXL, row, 11,
',', CSV_QUOTES);
263 foundValidDataRow = TRUE;
270 if (row[0] && row[8]) {
271 snprintf (pnpPartData.designator,
sizeof(pnpPartData.designator)-1,
"%s", row[0]);
272 snprintf (pnpPartData.footprint,
sizeof(pnpPartData.footprint)-1,
"%s", row[1]);
273 snprintf (pnpPartData.layer,
sizeof(pnpPartData.layer)-1,
"%s", row[8]);
274 if (row[10] != NULL) {
275 if ( ! g_utf8_validate(row[10], -1, NULL)) {
276 gchar * str = g_convert(row[10], strlen(row[10]),
"UTF-8",
"ISO-8859-1",
281 snprintf (pnpPartData.comment,
sizeof(pnpPartData.comment)-1,
"%s", str);
284 snprintf (pnpPartData.comment,
sizeof(pnpPartData.comment)-1,
"%s", row[10]);
299 sscanf(row[9],
"%lf", &pnpPartData.rotation);
304 else if (row[0] && row[1] && row[2] && row[3] && row[4] && row[5] && row[6]) {
305 snprintf (pnpPartData.designator,
sizeof(pnpPartData.designator)-1,
"%s", row[0]);
306 snprintf (pnpPartData.footprint,
sizeof(pnpPartData.footprint)-1,
"%s", row[1]);
307 snprintf (pnpPartData.layer,
sizeof(pnpPartData.layer)-1,
"%s", row[6]);
310 pnpPartData.pad_x = pnpPartData.mid_x + 0.03;
311 pnpPartData.pad_y = pnpPartData.mid_y + 0.03;
312 sscanf(row[5],
"%lf", &pnpPartData.rotation);
316 if ((fabs(pnpPartData.mid_x) < 0.001)&&(fabs(pnpPartData.mid_y) < 0.001)) {
328 if(sscanf(pnpPartData.footprint,
"%02d%02d", &i_length, &i_width) == 2) {
330 pnpPartData.length = 0.01 * i_length;
331 pnpPartData.width = 0.01 * i_width;
332 pnpPartData.shape = PART_SHAPE_RECTANGLE;
334 gerb_transf_reset(tr_rot);
336 gerb_transf_apply( pnpPartData.pad_x - pnpPartData.mid_x,
337 pnpPartData.pad_y - pnpPartData.mid_y, tr_rot, &tmp_x, &tmp_y);
338 if ((fabs(tmp_y) > fabs(tmp_x/100)) && (fabs(tmp_x) > fabs(tmp_y/100))){
339 pnpPartData.length = 2 * fabs(tmp_x);
340 pnpPartData.width = 2 * fabs(tmp_y);
341 pnpPartData.shape = PART_SHAPE_STD;
343 pnpPartData.length = 0.015;
344 pnpPartData.width = 0.015;
345 pnpPartData.shape = PART_SHAPE_UNKNOWN;
348 g_array_append_val (pnpParseDataArray, pnpPartData);
351 gerb_transf_free(tr_rot);
356 if ((((
float) parsedLines / (
float) lineCounter) < 0.3) ||
357 (!foundValidDataRow)) {
359 g_array_free (pnpParseDataArray, TRUE);
362 return pnpParseDataArray;
376 pick_and_place_check_file_type(gerb_file_t *fd, gboolean *returnFoundBinary)
382 gboolean found_binary = FALSE;
383 gboolean found_G54 = FALSE;
384 gboolean found_M0 = FALSE;
385 gboolean found_M2 = FALSE;
386 gboolean found_G2 = FALSE;
387 gboolean found_ADD = FALSE;
388 gboolean found_comma = FALSE;
389 gboolean found_R = FALSE;
390 gboolean found_U = FALSE;
391 gboolean found_C = FALSE;
392 gboolean found_boardside = FALSE;
396 GERB_FATAL_ERROR(_(
"malloc buf failed while checking for pick-place file."));
398 while (fgets(buf, MAXL, fd->fd) != NULL) {
404 for (i = 0; i < len; i++) {
405 if (!isprint((
int) buf[i]) && (buf[i] !=
'\r') &&
406 (buf[i] !=
'\n') && (buf[i] !=
'\t')) {
411 if (g_strstr_len(buf, len,
"G54")) {
414 if (g_strstr_len(buf, len,
"M00")) {
417 if (g_strstr_len(buf, len,
"M02")) {
420 if (g_strstr_len(buf, len,
"G02")) {
423 if (g_strstr_len(buf, len,
"ADD")) {
426 if (g_strstr_len(buf, len,
",")) {
430 if (g_strstr_len(buf, len,
";")) {
435 if ((letter = g_strstr_len(buf, len,
"R")) != NULL) {
436 if (isdigit((
int) letter[1])) {
440 if ((letter = g_strstr_len(buf, len,
"C")) != NULL) {
441 if (isdigit((
int) letter[1])) {
445 if ((letter = g_strstr_len(buf, len,
"U")) != NULL) {
446 if (isdigit((
int) letter[1])) {
453 if (g_strstr_len(buf, len,
"top")) {
454 found_boardside = TRUE;
456 if (g_strstr_len(buf, len,
"Top")) {
457 found_boardside = TRUE;
459 if (g_strstr_len(buf, len,
"TOP")) {
460 found_boardside = TRUE;
463 if (g_strstr_len(buf, len,
"ayer")) {
464 found_boardside = TRUE;
466 if (g_strstr_len(buf, len,
"AYER")) {
467 found_boardside = TRUE;
475 *returnFoundBinary = found_binary;
486 if (found_comma && (found_R || found_C || found_U) &&
503 pick_and_place_convert_pnp_data_to_image(GArray *parsedPickAndPlaceData, gint boardSide)
508 gerbv_transf_t *tr_rot = gerb_transf_new();
510 gboolean foundElement = FALSE;
514 for (i = 0; i < parsedPickAndPlaceData->len; i++) {
515 PnpPartData partData = g_array_index(parsedPickAndPlaceData, PnpPartData, i);
517 if ((boardSide == 0) && !((partData.layer[0]==
'b') || (partData.layer[0]==
'B')))
519 if ((boardSide == 1) && !((partData.layer[0]==
't') || (partData.layer[0]==
'T')))
529 GERB_FATAL_ERROR(_(
"malloc image failed"));
533 if (image->
format == NULL) {
534 GERB_FATAL_ERROR(_(
"malloc format failed"));
545 GERB_FATAL_ERROR(_(
"malloc pick_place_stats failed"));
552 pick_and_place_reset_bounding_box (curr_net);
553 image->
info->min_x = HUGE_VAL;
554 image->
info->min_y = HUGE_VAL;
555 image->
info->max_x = -HUGE_VAL;
556 image->
info->max_y = -HUGE_VAL;
558 image->
aperture[0] = (gerbv_aperture_t *)g_malloc0(
sizeof(gerbv_aperture_t));
562 image->
aperture[0]->parameter[0] = 0.01;
563 image->
aperture[0]->nuf_parameters = 1;
565 for (i = 0; i < parsedPickAndPlaceData->len; i++) {
566 PnpPartData partData = g_array_index(parsedPickAndPlaceData, PnpPartData, i);
567 float radius,labelOffset;
570 curr_net = curr_net->
next;
571 assert(curr_net != NULL);
575 if ((partData.rotation > 89) && (partData.rotation < 91))
576 labelOffset = fabs(partData.length/2);
577 else if ((partData.rotation > 179) && (partData.rotation < 181))
578 labelOffset = fabs(partData.width/2);
579 else if ((partData.rotation > 269) && (partData.rotation < 271))
580 labelOffset = fabs(partData.length/2);
581 else if ((partData.rotation > -91) && (partData.rotation < -89))
582 labelOffset = fabs(partData.length/2);
583 else if ((partData.rotation > -181) && (partData.rotation < -179))
584 labelOffset = fabs(partData.width/2);
585 else if ((partData.rotation > -271) && (partData.rotation < -269))
586 labelOffset = fabs(partData.length/2);
587 else labelOffset = fabs(partData.width/2);
589 partData.rotation *= M_PI/180;
591 if ((boardSide == 0) && !((partData.layer[0]==
'b') || (partData.layer[0]==
'B')))
593 if ((boardSide == 1) && !((partData.layer[0]==
't') || (partData.layer[0]==
'T')))
600 curr_net->
start_y = curr_net->
stop_y = partData.mid_y + labelOffset + 0.01;
606 pick_and_place_reset_bounding_box (curr_net);
608 gerb_transf_reset(tr_rot);
612 if ((partData.shape == PART_SHAPE_RECTANGLE) ||
613 (partData.shape == PART_SHAPE_STD)) {
617 curr_net = curr_net->
next;
618 assert(curr_net != NULL);
620 gerb_transf_apply(partData.length/2, partData.width/2, tr_rot,
622 gerb_transf_apply(-partData.length/2, partData.width/2, tr_rot,
625 #warning "Write unifying function"
626 if (strlen (partData.designator) > 0) {
627 curr_net->
label = g_string_new (partData.designator);
634 pick_and_place_reset_bounding_box (curr_net);
637 curr_net = curr_net->
next;
638 assert(curr_net != NULL);
640 gerb_transf_apply(-partData.length/2, partData.width/2, tr_rot,
642 gerb_transf_apply(-partData.length/2, -partData.width/2, tr_rot,
645 if (strlen (partData.designator) > 0) {
646 curr_net->
label = g_string_new (partData.designator);
653 pick_and_place_reset_bounding_box (curr_net);
656 curr_net = curr_net->
next;
657 assert(curr_net != NULL);
659 gerb_transf_apply(-partData.length/2, -partData.width/2, tr_rot,
661 gerb_transf_apply(partData.length/2, -partData.width/2, tr_rot,
664 if (strlen (partData.designator) > 0) {
665 curr_net->
label = g_string_new (partData.designator);
672 pick_and_place_reset_bounding_box (curr_net);
675 curr_net = curr_net->
next;
676 assert(curr_net != NULL);
678 gerb_transf_apply(partData.length/2, -partData.width/2, tr_rot,
680 gerb_transf_apply(partData.length/2, partData.width/2, tr_rot,
683 if (strlen (partData.designator) > 0) {
684 curr_net->
label = g_string_new (partData.designator);
691 pick_and_place_reset_bounding_box (curr_net);
694 curr_net = curr_net->
next;
695 assert(curr_net != NULL);
697 if (partData.shape == PART_SHAPE_RECTANGLE) {
698 gerb_transf_apply(partData.length/4, -partData.width/2, tr_rot,
700 gerb_transf_apply(partData.length/4, partData.width/2, tr_rot,
703 gerb_transf_apply(partData.length/4, partData.width/2, tr_rot,
705 gerb_transf_apply(partData.length/4, partData.width/4, tr_rot,
708 if (strlen (partData.designator) > 0) {
709 curr_net->
label = g_string_new (partData.designator);
716 pick_and_place_reset_bounding_box (curr_net);
719 curr_net = curr_net->
next;
720 assert(curr_net != NULL);
722 gerb_transf_apply(partData.length/2, partData.width/4, tr_rot,
724 gerb_transf_apply(partData.length/4, partData.width/4, tr_rot,
728 if (strlen (partData.designator) > 0) {
729 curr_net->
label = g_string_new (partData.designator);
736 pick_and_place_reset_bounding_box (curr_net);
739 radius = max (partData.length/2, partData.width/2);
743 curr_net->
start_x = partData.mid_x;
744 curr_net->
start_y = partData.mid_y;
745 gerb_transf_apply( partData.pad_x - partData.mid_x,
746 partData.pad_y - partData.mid_y, tr_rot, &tmp_x, &tmp_y);
751 if (strlen (partData.designator) > 0) {
752 curr_net->
label = g_string_new (partData.designator);
761 curr_net = curr_net->
next;
762 assert(curr_net != NULL);
764 curr_net->
start_x = partData.mid_x;
765 curr_net->
start_y = partData.mid_y;
766 curr_net->
stop_x = partData.pad_x;
767 curr_net->
stop_y = partData.pad_y;
769 if (strlen(partData.designator) > 0) {
770 curr_net->
label = g_string_new (partData.designator);
777 pick_and_place_reset_bounding_box (curr_net);
779 curr_net->
cirseg = g_new0 (gerbv_cirseg_t,1);
780 curr_net->
cirseg->angle1 = 0.0;
781 curr_net->
cirseg->angle2 = 360.0;
782 curr_net->
cirseg->cp_x = partData.mid_x;
783 curr_net->
cirseg->cp_y = partData.mid_y;
784 radius = sqrt((partData.pad_x-partData.mid_x)*(partData.pad_x-partData.mid_x) +
785 (partData.pad_y-partData.mid_y)*(partData.pad_y-partData.mid_y));
788 curr_net->
cirseg->width = 2*radius;
789 curr_net->
cirseg->height = 2*radius;
796 image->
info->min_x = min(image->
info->min_x, (partData.mid_x - radius - 0.02));
797 image->
info->min_y = min(image->
info->min_y, (partData.mid_y - radius - 0.02));
798 image->
info->max_x = max(image->
info->max_x, (partData.mid_x + radius + 0.02));
799 image->
info->max_y = max(image->
info->max_y, (partData.mid_y + radius + 0.02));
801 curr_net->
next = NULL;
803 gerb_transf_free(tr_rot);
819 pick_and_place_parse_file_to_images(gerb_file_t *fd,
gerbv_image_t **topImage,
824 if (parsedPickAndPlaceData != NULL) {
826 if (*bottomImage == NULL)
827 *bottomImage = pick_and_place_convert_pnp_data_to_image(parsedPickAndPlaceData, 0);
829 if (*topImage == NULL)
830 *topImage = pick_and_place_convert_pnp_data_to_image(parsedPickAndPlaceData, 1);
832 g_array_free (parsedPickAndPlaceData, TRUE);