static int PrintBOM (void) { char utcTime[64]; Coord x, y; double theta = 0.0; double sumx, sumy; int pinfound[MAXREFPINS]; double pinx[MAXREFPINS]; double piny[MAXREFPINS]; double pinangle[MAXREFPINS]; double padcentrex, padcentrey; double centroidx, centroidy; double pin1x, pin1y; int pin_cnt; int found_any_not_at_centroid; int found_any; time_t currenttime; FILE *fp; BomList *bom = NULL; char *name, *descr, *value,*fixed_rotation; int rpindex; fp = fopen (xy_filename, "w"); if (!fp) { gui->log ("Cannot open file %s for writing\n", xy_filename); return 1; } /* Create a portable timestamp. */ currenttime = time (NULL); { /* avoid gcc complaints */ const char *fmt = "%c UTC"; strftime (utcTime, sizeof (utcTime), fmt, gmtime (¤ttime)); } fprintf (fp, "# PcbXY Version 1.0\n"); fprintf (fp, "# Date: %s\n", utcTime); fprintf (fp, "# Author: %s\n", pcb_author ()); fprintf (fp, "# Title: %s - PCB X-Y\n", UNKNOWN (PCB->Name)); fprintf (fp, "# RefDes, Description, Value, X, Y, rotation, top/bottom\n"); /* don't use localized xy_unit->in_suffix here since */ /* the line itself is not localized and not for GUI */ fprintf (fp, "# X,Y in %s. rotation in degrees.\n", xy_unit->suffix); fprintf (fp, "# --------------------------------------------\n"); /* * For each element we calculate the centroid of the footprint. * In addition, we need to extract some notion of rotation. * While here generate the BOM list */ ELEMENT_LOOP (PCB->Data); { /* Initialize our pin count and our totals for finding the centroid. */ pin_cnt = 0; sumx = 0.0; sumy = 0.0; for (rpindex = 0; rpindex < MAXREFPINS; rpindex++) pinfound[rpindex] = 0; /* Insert this component into the bill of materials list. */ bom = bom_insert ((char *)UNKNOWN (NAMEONPCB_NAME (element)), (char *)UNKNOWN (DESCRIPTION_NAME (element)), (char *)UNKNOWN (VALUE_NAME (element)), bom); /* * Iterate over the pins and pads keeping a running count of how * many pins/pads total and the sum of x and y coordinates * * While we're at it, store the location of pin/pad #1 and #2 if * we can find them. */ PIN_LOOP (element); { sumx += (double) pin->X; sumy += (double) pin->Y; pin_cnt++; for (rpindex = 0; reference_pin_names[rpindex]; rpindex++) { if (NSTRCMP (pin->Number, reference_pin_names[rpindex]) == 0) { pinx[rpindex] = (double) pin->X; piny[rpindex] = (double) pin->Y; pinangle[rpindex] = 0.0; /* pins have no notion of angle */ pinfound[rpindex] = 1; } } } END_LOOP; PAD_LOOP (element); { sumx += (pad->Point1.X + pad->Point2.X) / 2.0; sumy += (pad->Point1.Y + pad->Point2.Y) / 2.0; pin_cnt++; for (rpindex = 0; reference_pin_names[rpindex]; rpindex++) { if (NSTRCMP (pad->Number, reference_pin_names[rpindex]) == 0) { padcentrex = (double) (pad->Point1.X + pad->Point2.X) / 2.0; padcentrey = (double) (pad->Point1.Y + pad->Point2.Y) / 2.0; pinx[rpindex] = padcentrex; piny[rpindex] = padcentrey; /* * NOTE: We swap the Y points because in PCB, the Y-axis * is inverted. Increasing Y moves down. We want to deal * in the usual increasing Y moves up coordinates though. */ pinangle[rpindex] = (180.0 / M_PI) * atan2 (pad->Point1.Y - pad->Point2.Y, pad->Point2.X - pad->Point1.X); pinfound[rpindex]=1; } } } END_LOOP; if (pin_cnt > 0) { centroidx = sumx / (double) pin_cnt; centroidy = sumy / (double) pin_cnt; if (NSTRCMP( AttributeGetFromList (&element->Attributes,"xy-centre"), "origin") == 0 ) { x = element->MarkX; y = element->MarkY; } else { x = centroidx; y = centroidy; } fixed_rotation = AttributeGetFromList (&element->Attributes, "xy-fixed-rotation"); if (fixed_rotation) { /* The user specified a fixed rotation */ theta = atof (fixed_rotation); found_any_not_at_centroid = 1; found_any = 1; } else { /* Find first reference pin not at the centroid */ found_any_not_at_centroid = 0; found_any = 0; theta = 0.0; for (rpindex = 0; reference_pin_names[rpindex] && !found_any_not_at_centroid; rpindex++) { if (pinfound[rpindex]) { found_any = 1; /* Recenter pin "#1" onto the axis which cross at the part centroid */ pin1x = pinx[rpindex] - x; pin1y = piny[rpindex] - y; /* flip x, to reverse rotation for elements on back */ if (FRONT (element) != 1) pin1x = -pin1x; /* if only 1 pin, use pin 1's angle */ if (pin_cnt == 1) { theta = pinangle[rpindex]; found_any_not_at_centroid = 1; } else if ((pin1x != 0.0) || (pin1y != 0.0)) { theta = xyToAngle (pin1x, pin1y, pin_cnt > 2); found_any_not_at_centroid = 1; } } } if (!found_any) { Message ("PrintBOM(): unable to figure out angle because I could\n" " not find a suitable reference pin of element %s\n" " Setting to %g degrees\n", UNKNOWN (NAMEONPCB_NAME (element)), theta); } else if (!found_any_not_at_centroid) { Message ("PrintBOM(): unable to figure out angle of element\n" " %s because the reference pin(s) are at the centroid of the part.\n" " Setting to %g degrees\n", UNKNOWN (NAMEONPCB_NAME (element)), theta); } } name = CleanBOMString ((char *)UNKNOWN (NAMEONPCB_NAME (element))); descr = CleanBOMString ((char *)UNKNOWN (DESCRIPTION_NAME (element))); value = CleanBOMString ((char *)UNKNOWN (VALUE_NAME (element))); y = PCB->MaxHeight - y; pcb_fprintf (fp, "%m+%s,\"%s\",\"%s\",%.2mS,%.2mS,%g,%s\n", xy_unit->allow, name, descr, value, x, y, theta, FRONT (element) == 1 ? "top" : "bottom"); free (name); free (descr); free (value); } } END_LOOP; fclose (fp); /* Now print out a Bill of Materials file */ fp = fopen (bom_filename, "w"); if (!fp) { gui->log ("Cannot open file %s for writing\n", bom_filename); print_and_free (NULL, bom); return 1; } fprintf (fp, "# PcbBOM Version 1.0\n"); fprintf (fp, "# Date: %s\n", utcTime); fprintf (fp, "# Author: %s\n", pcb_author ()); fprintf (fp, "# Title: %s - PCB BOM\n", UNKNOWN (PCB->Name)); fprintf (fp, "# Quantity, Description, Value, RefDes\n"); fprintf (fp, "# --------------------------------------------\n"); print_and_free (fp, bom); fclose (fp); return (0); }
static int PrintBOM (void) { char utcTime[64]; Coord x, y; double theta = 0.0; double sumx, sumy; double pin1x = 0.0, pin1y = 0.0, pin1angle = 0.0; double pin2x = 0.0, pin2y = 0.0; int found_pin1; int found_pin2; int pin_cnt; time_t currenttime; FILE *fp; BomList *bom = NULL; char *name, *descr, *value; fp = fopen (xy_filename, "w"); if (!fp) { gui->log ("Cannot open file %s for writing\n", xy_filename); return 1; } /* Create a portable timestamp. */ currenttime = time (NULL); { /* avoid gcc complaints */ const char *fmt = "%c UTC"; strftime (utcTime, sizeof (utcTime), fmt, gmtime (¤ttime)); } fprintf (fp, "# PcbXY Version 1.0\n"); fprintf (fp, "# Date: %s\n", utcTime); fprintf (fp, "# Author: %s\n", pcb_author ()); fprintf (fp, "# Title: %s - PCB X-Y\n", UNKNOWN (PCB->Name)); fprintf (fp, "# RefDes, Description, Value, X, Y, rotation, top/bottom\n"); fprintf (fp, "# X,Y in %s. rotation in degrees.\n", xy_unit->in_suffix); fprintf (fp, "# --------------------------------------------\n"); /* * For each element we calculate the centroid of the footprint. * In addition, we need to extract some notion of rotation. * While here generate the BOM list */ ELEMENT_LOOP (PCB->Data); { /* initialize our pin count and our totals for finding the centriod */ pin_cnt = 0; sumx = 0.0; sumy = 0.0; found_pin1 = 0; found_pin2 = 0; /* insert this component into the bill of materials list */ bom = bom_insert ((char *)UNKNOWN (NAMEONPCB_NAME (element)), (char *)UNKNOWN (DESCRIPTION_NAME (element)), (char *)UNKNOWN (VALUE_NAME (element)), bom); /* * iterate over the pins and pads keeping a running count of how * many pins/pads total and the sum of x and y coordinates * * While we're at it, store the location of pin/pad #1 and #2 if * we can find them */ PIN_LOOP (element); { sumx += (double) pin->X; sumy += (double) pin->Y; pin_cnt++; if (NSTRCMP (pin->Number, "1") == 0) { pin1x = (double) pin->X; pin1y = (double) pin->Y; pin1angle = 0.0; /* pins have no notion of angle */ found_pin1 = 1; } else if (NSTRCMP (pin->Number, "2") == 0) { pin2x = (double) pin->X; pin2y = (double) pin->Y; found_pin2 = 1; } } END_LOOP; PAD_LOOP (element); { sumx += (pad->Point1.X + pad->Point2.X) / 2.0; sumy += (pad->Point1.Y + pad->Point2.Y) / 2.0; pin_cnt++; if (NSTRCMP (pad->Number, "1") == 0) { pin1x = (double) (pad->Point1.X + pad->Point2.X) / 2.0; pin1y = (double) (pad->Point1.Y + pad->Point2.Y) / 2.0; /* * NOTE: We swap the Y points because in PCB, the Y-axis * is inverted. Increasing Y moves down. We want to deal * in the usual increasing Y moves up coordinates though. */ pin1angle = (180.0 / M_PI) * atan2 (pad->Point1.Y - pad->Point2.Y, pad->Point2.X - pad->Point1.X); found_pin1 = 1; } else if (NSTRCMP (pad->Number, "2") == 0) { pin2x = (double) (pad->Point1.X + pad->Point2.X) / 2.0; pin2y = (double) (pad->Point1.Y + pad->Point2.Y) / 2.0; found_pin2 = 1; } } END_LOOP; if (pin_cnt > 0) { x = sumx / (double) pin_cnt; y = sumy / (double) pin_cnt; if (found_pin1) { /* recenter pin #1 onto the axis which cross at the part centroid */ pin1x -= x; pin1y -= y; pin1y = -1.0 * pin1y; /* if only 1 pin, use pin 1's angle */ if (pin_cnt == 1) theta = pin1angle; else { /* if pin #1 is at (0,0) use pin #2 for rotation */ if ((pin1x == 0.0) && (pin1y == 0.0)) { if (found_pin2) theta = xyToAngle (pin2x, pin2y); else { Message ("PrintBOM(): unable to figure out angle of element\n" " %s because pin #1 is at the centroid of the part.\n" " and I could not find pin #2's location\n" " Setting to %g degrees\n", UNKNOWN (NAMEONPCB_NAME (element)), theta); } } else theta = xyToAngle (pin1x, pin1y); } } /* we did not find pin #1 */ else { theta = 0.0; Message ("PrintBOM(): unable to figure out angle because I could\n" " not find pin #1 of element %s\n" " Setting to %g degrees\n", UNKNOWN (NAMEONPCB_NAME (element)), theta); } name = CleanBOMString ((char *)UNKNOWN (NAMEONPCB_NAME (element))); descr = CleanBOMString ((char *)UNKNOWN (DESCRIPTION_NAME (element))); value = CleanBOMString ((char *)UNKNOWN (VALUE_NAME (element))); y = PCB->MaxHeight - y; pcb_fprintf (fp, "%m+%s,\"%s\",\"%s\",%mS,%.2mS,%g,%s\n", xy_unit->allow, name, descr, value, x, y, theta, FRONT (element) == 1 ? "top" : "bottom"); free (name); free (descr); free (value); } } END_LOOP; fclose (fp); /* Now print out a Bill of Materials file */ fp = fopen (bom_filename, "w"); if (!fp) { gui->log ("Cannot open file %s for writing\n", bom_filename); print_and_free (NULL, bom); return 1; } fprintf (fp, "# PcbBOM Version 1.0\n"); fprintf (fp, "# Date: %s\n", utcTime); fprintf (fp, "# Author: %s\n", pcb_author ()); fprintf (fp, "# Title: %s - PCB BOM\n", UNKNOWN (PCB->Name)); fprintf (fp, "# Quantity, Description, Value, RefDes\n"); fprintf (fp, "# --------------------------------------------\n"); print_and_free (fp, bom); fclose (fp); return (0); }