47 void gerb_transf_free(gerbv_transf_t *transf)
53 void gerb_transf_reset(gerbv_transf_t* transf)
55 memset(transf,0,
sizeof(gerbv_transf_t));
57 transf->r_mat[0][0] = transf->r_mat[1][1] = 1.0;
65 gerbv_transf_t* gerb_transf_new(
void)
67 gerbv_transf_t *transf;
69 transf = g_new(gerbv_transf_t, 1);
70 gerb_transf_reset(transf);
84 double s = sin(angle), c = cos(angle);
86 memcpy(m, transf->r_mat,
sizeof(m));
87 transf->r_mat[0][0] = c * m[0][0] - s * m[1][0];
88 transf->r_mat[0][1] = c * m[0][1] - s * m[1][1];
89 transf->r_mat[1][0] = s * m[0][0] + c * m[1][0];
90 transf->r_mat[1][1] = s * m[0][1] + c * m[1][1];
104 transf->offset[0] += shift_x;
105 transf->offset[1] += shift_y;
109 void gerb_transf_apply(
double x,
double y, gerbv_transf_t* transf,
double *out_x,
double *out_y)
114 *out_x = (x * transf->r_mat[0][0] + y * transf->r_mat[0][1]) * transf->scale;
115 *out_y = (x * transf->r_mat[1][0] + y * transf->r_mat[1][1]) * transf->scale;
116 *out_x += transf->offset[0];
117 *out_y += transf->offset[1];
123 pick_and_place_reset_bounding_box (
gerbv_net_t *net) {
133 pick_and_place_get_float_unit(
const char *str,
const char *def_unit)
136 char unit_str[41] = {0,};
137 const char *unit = unit_str;
140 sscanf(str,
"%lf %40s", &x, unit_str);
142 if (unit_str[0] ==
'\0')
147 if (strstr(unit,
"mm")) {
149 }
else if (strstr(unit,
"in")) {
151 }
else if (strstr(unit,
"cmil")) {
153 }
else if (strstr(unit,
"dmil")) {
155 }
else if (strstr(unit,
"mil")) {
157 }
else if (strstr(unit,
"km")) {
159 }
else if (strstr(unit,
"dm")) {
161 }
else if (strstr(unit,
"cm")) {
163 }
else if (strstr(unit,
"um")) {
165 }
else if (strstr(unit,
"nm")) {
167 }
else if (strstr(unit,
"m")) {
183 char delimiter[4] =
"|,;:";
185 int idx, idx_max = 0;
187 memset(counter, 0,
sizeof(counter));
188 for(ptr = str; *ptr; ptr++) {
207 if(counter[idx] > counter[idx_max]) {
212 if (counter[idx_max] > n) {
213 return (
unsigned char) delimiter[idx_max];
229 PnpPartData pnpPartData;
230 memset(&pnpPartData, 0,
sizeof(PnpPartData));
231 int lineCounter = 0, parsedLines = 0;
234 char buf[MAXL+2], buf0[MAXL+2];
235 char def_unit[41] = {0,};
237 gerbv_transf_t *tr_rot = gerb_transf_new();
238 GArray *pnpParseDataArray = g_array_new (FALSE, FALSE,
sizeof(PnpPartData));
239 gboolean foundValidDataRow = FALSE;
241 const char *def_unit_prefix =
"# X,Y in ";
247 setlocale(LC_NUMERIC,
"C" );
249 while ( fgets(buf, MAXL, fd->fd) != NULL ) {
250 int len = strlen(buf)-1;
251 int i_length = 0, i_width = 0;
254 if(lineCounter < 2) {
261 if(len >= 0 && buf[len] ==
'\n') {
264 if(len >= 0 && buf[len] ==
'\r') {
267 if (0 == strncmp(buf, def_unit_prefix, strlen(def_unit_prefix))) {
268 sscanf(&buf[strlen(def_unit_prefix)],
"%40s.", def_unit);
274 if ((len > 0) && (buf[0] ==
'%')) {
279 if ((len > 4) && (strncmp(buf,
"G54 ", 4) == 0)) {
280 g_array_free (pnpParseDataArray, TRUE);
285 if ((len > 4) && (strncmp(buf,
"G04 ", 4) == 0)) {
286 g_array_free (pnpParseDataArray, TRUE);
297 ret = csv_row_parse(buf, MAXL, buf0, MAXL, row, 11,
',', CSV_QUOTES);
300 foundValidDataRow = TRUE;
307 if (row[0] && row[8]) {
308 snprintf (pnpPartData.designator,
sizeof(pnpPartData.designator)-1,
"%s", row[0]);
309 snprintf (pnpPartData.footprint,
sizeof(pnpPartData.footprint)-1,
"%s", row[1]);
310 snprintf (pnpPartData.layer,
sizeof(pnpPartData.layer)-1,
"%s", row[8]);
311 if (row[10] != NULL) {
312 if ( ! g_utf8_validate(row[10], -1, NULL)) {
313 gchar * str = g_convert(row[10], strlen(row[10]),
"UTF-8",
"ISO-8859-1",
318 snprintf (pnpPartData.comment,
sizeof(pnpPartData.comment)-1,
"%s", str);
321 snprintf (pnpPartData.comment,
sizeof(pnpPartData.comment)-1,
"%s", row[10]);
327 pnpPartData.mid_x = pick_and_place_get_float_unit(row[2], def_unit);
328 pnpPartData.mid_y = pick_and_place_get_float_unit(row[3], def_unit);
329 pnpPartData.ref_x = pick_and_place_get_float_unit(row[4], def_unit);
330 pnpPartData.ref_y = pick_and_place_get_float_unit(row[5], def_unit);
331 pnpPartData.pad_x = pick_and_place_get_float_unit(row[6], def_unit);
332 pnpPartData.pad_y = pick_and_place_get_float_unit(row[7], def_unit);
336 int const rc = sscanf(row[9],
"%lf", &pnpPartData.rotation);
341 g_array_free (pnpParseDataArray, TRUE);
349 else if (row[0] && row[1] && row[2] && row[3] && row[4] && row[5] && row[6]) {
350 snprintf (pnpPartData.designator,
sizeof(pnpPartData.designator)-1,
"%s", row[0]);
351 snprintf (pnpPartData.footprint,
sizeof(pnpPartData.footprint)-1,
"%s", row[1]);
352 snprintf (pnpPartData.layer,
sizeof(pnpPartData.layer)-1,
"%s", row[6]);
353 pnpPartData.mid_x = pick_and_place_get_float_unit(row[3], def_unit);
354 pnpPartData.mid_y = pick_and_place_get_float_unit(row[4], def_unit);
355 pnpPartData.pad_x = pnpPartData.mid_x + 0.03;
356 pnpPartData.pad_y = pnpPartData.mid_y + 0.03;
361 if ((fabs(pnpPartData.mid_x) < 0.001)&&(fabs(pnpPartData.mid_y) < 0.001)) {
367 int const rc = sscanf(row[5],
"%lf", &pnpPartData.rotation);
369 g_array_free (pnpParseDataArray, TRUE);
381 if(sscanf(pnpPartData.footprint,
"%02d%02d", &i_length, &i_width) == 2) {
383 pnpPartData.length = 0.01 * i_length;
384 pnpPartData.width = 0.01 * i_width;
385 pnpPartData.shape = PART_SHAPE_RECTANGLE;
387 gerb_transf_reset(tr_rot);
389 gerb_transf_apply( pnpPartData.pad_x - pnpPartData.mid_x,
390 pnpPartData.pad_y - pnpPartData.mid_y, tr_rot, &tmp_x, &tmp_y);
391 if ((fabs(tmp_y) > fabs(tmp_x/100)) && (fabs(tmp_x) > fabs(tmp_y/100))){
392 pnpPartData.length = 2 * fabs(tmp_x);
393 pnpPartData.width = 2 * fabs(tmp_y);
394 pnpPartData.shape = PART_SHAPE_STD;
396 pnpPartData.length = 0.015;
397 pnpPartData.width = 0.015;
398 pnpPartData.shape = PART_SHAPE_UNKNOWN;
401 g_array_append_val (pnpParseDataArray, pnpPartData);
404 gerb_transf_free(tr_rot);
409 if ((((
float) parsedLines / (
float) lineCounter) < 0.3) ||
410 (!foundValidDataRow)) {
412 g_array_free (pnpParseDataArray, TRUE);
415 return pnpParseDataArray;
429 pick_and_place_check_file_type(gerb_file_t *fd, gboolean *returnFoundBinary)
435 gboolean found_binary = FALSE;
436 gboolean found_G54 = FALSE;
437 gboolean found_M0 = FALSE;
438 gboolean found_M2 = FALSE;
439 gboolean found_G2 = FALSE;
440 gboolean found_ADD = FALSE;
441 gboolean found_comma = FALSE;
442 gboolean found_R = FALSE;
443 gboolean found_U = FALSE;
444 gboolean found_C = FALSE;
445 gboolean found_boardside = FALSE;
449 GERB_FATAL_ERROR(
"malloc buf failed in %s()", __FUNCTION__);
451 while (fgets(buf, MAXL, fd->fd) != NULL) {
457 for (i = 0; i < len; i++) {
458 if (!isprint((
int) buf[i]) && (buf[i] !=
'\r') &&
459 (buf[i] !=
'\n') && (buf[i] !=
'\t')) {
464 if (g_strstr_len(buf, len,
"G54")) {
467 if (g_strstr_len(buf, len,
"M00")) {
470 if (g_strstr_len(buf, len,
"M02")) {
473 if (g_strstr_len(buf, len,
"G02")) {
476 if (g_strstr_len(buf, len,
"ADD")) {
479 if (g_strstr_len(buf, len,
",")) {
483 if (g_strstr_len(buf, len,
";")) {
488 if ((letter = g_strstr_len(buf, len,
"R")) != NULL) {
489 if (isdigit((
int) letter[1])) {
493 if ((letter = g_strstr_len(buf, len,
"C")) != NULL) {
494 if (isdigit((
int) letter[1])) {
498 if ((letter = g_strstr_len(buf, len,
"U")) != NULL) {
499 if (isdigit((
int) letter[1])) {
506 if (g_strstr_len(buf, len,
"top")) {
507 found_boardside = TRUE;
509 if (g_strstr_len(buf, len,
"Top")) {
510 found_boardside = TRUE;
512 if (g_strstr_len(buf, len,
"TOP")) {
513 found_boardside = TRUE;
516 if (g_strstr_len(buf, len,
"ayer")) {
517 found_boardside = TRUE;
519 if (g_strstr_len(buf, len,
"AYER")) {
520 found_boardside = TRUE;
528 *returnFoundBinary = found_binary;
539 if (found_comma && (found_R || found_C || found_U) &&
556 pick_and_place_convert_pnp_data_to_image(GArray *parsedPickAndPlaceData, gint boardSide)
560 gerbv_transf_t *tr_rot = gerb_transf_new();
562 gboolean foundElement = FALSE;
563 const double draw_width = 0.01;
567 for (guint i = 0; i < parsedPickAndPlaceData->len; i++) {
568 PnpPartData partData = g_array_index(parsedPickAndPlaceData, PnpPartData, i);
570 if ((boardSide == 0) && !((partData.layer[0]==
'b') || (partData.layer[0]==
'B')))
572 if ((boardSide == 1) && !((partData.layer[0]==
't') || (partData.layer[0]==
'T')))
582 GERB_FATAL_ERROR(
"malloc image failed in %s()", __FUNCTION__);
586 if (image->
format == NULL) {
587 GERB_FATAL_ERROR(
"malloc format failed in %s()", __FUNCTION__);
598 GERB_FATAL_ERROR(
"malloc pick_place_stats failed in %s()",
606 pnp_reset_bbox (curr_net);
607 image->
info->min_x = HUGE_VAL;
608 image->
info->min_y = HUGE_VAL;
609 image->
info->max_x = -HUGE_VAL;
610 image->
info->max_y = -HUGE_VAL;
612 image->
aperture[0] = g_new0(gerbv_aperture_t, 1);
616 image->
aperture[0]->parameter[0] = draw_width;
617 image->
aperture[0]->nuf_parameters = 1;
619 for (guint i = 0; i < parsedPickAndPlaceData->len; i++) {
620 PnpPartData partData = g_array_index(parsedPickAndPlaceData, PnpPartData, i);
621 float radius,labelOffset;
623 curr_net = pnp_new_net(curr_net);
627 if ((partData.rotation > 89) && (partData.rotation < 91))
628 labelOffset = fabs(partData.length/2);
629 else if ((partData.rotation > 179) && (partData.rotation < 181))
630 labelOffset = fabs(partData.width/2);
631 else if ((partData.rotation > 269) && (partData.rotation < 271))
632 labelOffset = fabs(partData.length/2);
633 else if ((partData.rotation > -91) && (partData.rotation < -89))
634 labelOffset = fabs(partData.length/2);
635 else if ((partData.rotation > -181) && (partData.rotation < -179))
636 labelOffset = fabs(partData.width/2);
637 else if ((partData.rotation > -271) && (partData.rotation < -269))
638 labelOffset = fabs(partData.length/2);
639 else labelOffset = fabs(partData.width/2);
641 partData.rotation = DEG2RAD(partData.rotation);
644 if ((boardSide == 0) && !((partData.layer[0]==
'b') || (partData.layer[0]==
'B')))
646 if ((boardSide == 1) && !((partData.layer[0]==
't') || (partData.layer[0]==
'T')))
649 curr_net = pnp_new_net(curr_net);
650 pnp_init_net(curr_net, image, partData.designator,
658 partData.mid_y + labelOffset + draw_width;
660 gerb_transf_reset(tr_rot);
664 if ((partData.shape == PART_SHAPE_RECTANGLE) ||
665 (partData.shape == PART_SHAPE_STD)) {
668 curr_net = pnp_new_net(curr_net);
669 pnp_init_net(curr_net, image, partData.designator,
673 gerb_transf_apply(partData.length/2, partData.width/2, tr_rot,
675 gerb_transf_apply(-partData.length/2, partData.width/2, tr_rot,
680 curr_net = pnp_new_net(curr_net);
681 pnp_init_net(curr_net, image, partData.designator,
685 gerb_transf_apply(-partData.length/2, partData.width/2, tr_rot,
687 gerb_transf_apply(-partData.length/2, -partData.width/2, tr_rot,
690 curr_net = pnp_new_net(curr_net);
691 pnp_init_net(curr_net, image, partData.designator,
695 gerb_transf_apply(-partData.length/2, -partData.width/2, tr_rot,
697 gerb_transf_apply(partData.length/2, -partData.width/2, tr_rot,
700 curr_net = pnp_new_net(curr_net);
701 pnp_init_net(curr_net, image, partData.designator,
705 gerb_transf_apply(partData.length/2, -partData.width/2, tr_rot,
707 gerb_transf_apply(partData.length/2, partData.width/2, tr_rot,
710 curr_net = pnp_new_net(curr_net);
711 pnp_init_net(curr_net, image, partData.designator,
715 if (partData.shape == PART_SHAPE_RECTANGLE) {
716 gerb_transf_apply(partData.length/4, -partData.width/2, tr_rot,
718 gerb_transf_apply(partData.length/4, partData.width/2, tr_rot,
721 gerb_transf_apply(partData.length/4, partData.width/2, tr_rot,
723 gerb_transf_apply(partData.length/4, partData.width/4, tr_rot,
726 curr_net = pnp_new_net(curr_net);
727 pnp_init_net(curr_net, image, partData.designator,
731 gerb_transf_apply(partData.length/2, partData.width/4, tr_rot,
733 gerb_transf_apply(partData.length/4, partData.width/4, tr_rot,
738 radius = MAX(partData.length/2, partData.width/2);
742 pnp_init_net(curr_net, image, partData.designator,
746 curr_net->
start_x = partData.mid_x;
747 curr_net->
start_y = partData.mid_y;
748 gerb_transf_apply( partData.pad_x - partData.mid_x,
749 partData.pad_y - partData.mid_y, tr_rot, &tmp_x, &tmp_y);
755 curr_net = pnp_new_net(curr_net);
756 pnp_init_net(curr_net, image, partData.designator,
760 curr_net->
start_x = partData.mid_x;
761 curr_net->
start_y = partData.mid_y;
762 curr_net->
stop_x = partData.pad_x;
763 curr_net->
stop_y = partData.pad_y;
765 curr_net->
cirseg = g_new0 (gerbv_cirseg_t, 1);
766 curr_net->
cirseg->angle1 = 0.0;
767 curr_net->
cirseg->angle2 = 360.0;
768 curr_net->
cirseg->cp_x = partData.mid_x;
769 curr_net->
cirseg->cp_y = partData.mid_y;
770 radius = hypot(partData.pad_x - partData.mid_x,
771 partData.pad_y-partData.mid_y);
774 curr_net->
cirseg->width = 2*radius;
775 curr_net->
cirseg->height = 2*radius;
782 image->
info->min_x = MIN(image->
info->min_x, (partData.mid_x - radius - 0.02));
783 image->
info->min_y = MIN(image->
info->min_y, (partData.mid_y - radius - 0.02));
784 image->
info->max_x = MAX(image->
info->max_x, (partData.mid_x + radius + 0.02));
785 image->
info->max_y = MAX(image->
info->max_y, (partData.mid_y + radius + 0.02));
787 curr_net->
next = NULL;
789 gerb_transf_free(tr_rot);
805 pick_and_place_parse_file_to_images(gerb_file_t *fd,
gerbv_image_t **topImage,
810 if (parsedPickAndPlaceData != NULL) {
812 if (*bottomImage == NULL)
813 *bottomImage = pick_and_place_convert_pnp_data_to_image(parsedPickAndPlaceData, 0);
815 if (*topImage == NULL)
816 *topImage = pick_and_place_convert_pnp_data_to_image(parsedPickAndPlaceData, 1);
818 g_array_free (parsedPickAndPlaceData, TRUE);
855 if (strlen(label) > 0) {
856 net->
label = g_string_new (label);
Header info for the parsing support functions for the pick and place parser.
gerbv_drill_stats_t * gerbv_drill_stats_new(void)
Allocates a new drill_stats structure.
gerbv_image_t * gerbv_create_image(gerbv_image_t *image, const gchar *type)
Allocate a new gerbv_image structure.
Header info for the RS274X parsing functions.
The main header file for the libgerbv library.
@ GERBV_APERTURE_STATE_OFF
@ GERBV_APERTURE_STATE_ON
@ GERBV_INTERPOLATION_CW_CIRCULAR
@ GERBV_INTERPOLATION_LINEARx1
@ GERBV_LAYERTYPE_PICKANDPLACE_BOT
@ GERBV_LAYERTYPE_PICKANDPLACE_TOP
void gerb_transf_rotate(gerbv_transf_t *transf, double angle)
Rotation.
void gerb_transf_shift(gerbv_transf_t *transf, double shift_x, double shift_y)
Translation.
GArray * pick_and_place_parse_file(gerb_file_t *fd)
Parses the PNP data.
int pick_and_place_screen_for_delimiter(char *str, int n)
search a string for a delimiter.
Header info for the PNP (pick-and-place) parsing functions.
gerbv_layertype_t layertype
gerbv_drill_stats_t * drill_stats
gerbv_aperture_t * aperture[APERTURE_MAX]
gerbv_netstate_t * states
gerbv_image_info_t * info
gerbv_render_size_t boundingBox
gerbv_aperture_state_t aperture_state
gerbv_interpolation_t interpolation