* An Automated approach to beam design. This is an interactive program
* Designed to take input about a beam and then determine beam para-
* meters, which are displayed both graphically and numerically.
* After on screen design a hardcopy may be made on an Epson compatible
* printer. The program requires an EGA quality monitor, with an IBM
/* header files which define functions and constants */
/* define internal operation and error codes */
/* set corners of user input box */
/* miscellaneous definitions */
#define EXTENSION 20 /* standoff for dimensions */
#define DOUBLE_LINE_GAP .005 /* normalized gap between double lines */
#define X_Y_RATIO 1.408 /* Screen x to y aspect ratio */
#define PAGE_OFFSET 80 /* Output offset for printer */
#define ERROR_BIT 8 /* Printer error bit */
/* declare functions in this listing */
/* set up formats for user inputs, prompts and help prompts */
struct entry list[8] = {{{“Beam Type :”}, .08, .18,
{“3. Solid 4. Hollow 5. L-Beam”}},
{{“Beam Material :”}, .08, .23,
{{“Beam Thickness :”}, .08, .33,
{“Metal Plat thickness for beam “},
{“Total height of beam from top to bottom”}},
{“Total width of beam from left to right”}},
{“Length of unsuported span to be”},
{{“Load Position Offset :”}, .08, .58,
{“Distance from left side to the Point”},
{“at which a load force is applied”}},
{“Total load force applied at load”},
/* set up format and structure for material description */
struct mats materials[10] = {{{“Steel”}, .283, 10300000.0},
{{“Aluminum”}, .0995, 29000000.0}};
/* set up work strings and various beam names */
int beam_type = I_BEAM, /* beam cross section type */
beam_material = STEEL, /* beam material used */
entry_number = 0; /* Current choice on input menu */
/* set up global double precision numbers */
double beam_width = 3.0, /* Width of beam cross section */
beam_height = 6.0, /* Height of Beam cross section */
beam_thick = 0.5, /* Thickness of metal plates */
beam_length = 120.0, /* Length of beam span */
beam_load = 0.0, /* Load force applied to beam */
beam_point = 0.0, /* displacement of applied load */
beam_area, /* calculated cross section area */
x_centroid, /* calculated x centroid */
y_centroid, /* calculated y centroid */
moment_inertia, /* Calculated moment of inertia */
x_axis, /* calculated x principal axis */
y_axis, /* calculated y principal axis */
axial_stiffness, /* calculated axial stiffness */
bending_stiffness, /* calculated bending stiffness */
beam_deflect, /* calculated beam deflection */
deflect_point, /* point of maximum deflection */
out_distance, /* calculated distance from fibres */
beam_weight, /* calculated total beam weight */
xmax, /* absolute width of screen x */
ymax; /* absolute height of screen y */
* This is the main terminal point between the various stages of setup,
* input, revision and termination.
if((error = setup()) != ERROR) {
while((error = input()) != DONE) {
printf(“EGA Graphics Driver Not Installed”);
* This will initialize an EGA monitor and then initialize, and collect
* video parameters, and initialize the printer.
/* Detect EGA driver and initialize */
initgraph(&driver, &mode, ““);
/* get maximum x and y screen pixel coordinates */
* This section will set up the screen with basic titles and headings.
* The section will also update the current values of beam parameters.
/* If instructed then clear screen and add titles */
/* Add titles and instructions */
draw_line(.50, 0.0, .50, 1.0-DOUBLE_LINE_GAP);
draw_line(.5 + DOUBLE_LINE_GAP, 0.0, .5 + DOUBLE_LINE_GAP, 1.0-DOUBLE_LINE_GAP);
settextstyle(SANS_SERIF_FONT, HORIZ_DIR, 4);
text(.02, .014, “Beam C.A.D.”);
settextstyle(SMALL_FONT, HORIZ_DIR, 6);
text(.31, .06, “by Hugh Jack”);
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
text(INPUT_LEFT, INPUT_TOP - .10, “F1 - QUIT F3 - SCREEN PRINT F4 - HARDCOPY”);
text(INPUT_LEFT, INPUT_TOP - .07, “Use UP and DOWN Cursors to select Parameter”);
text(INPUT_LEFT, INPUT_TOP - .04, “enter new paramter and press RETURN to accept”);
box(INPUT_LEFT, INPUT_BOTTOM, INPUT_RIGHT, INPUT_TOP, GREEN, NEW);
/* If instructed then update beam information */
/* Calculate new output parameters from input parameters */
sprintf(work, “Type : %s”, beams[beam_type]);
sprintf(work, “Material : %s”, materials[beam_material].name);
text(.05, .28, “Cross Section”);
sprintf(work, “Thickness : %.3f in.”, beam_thick);
sprintf(work, “Height : %.3f in.”, beam_height);
sprintf(work, “Width : %.3f in.”, beam_width);
sprintf(work, “Length : %.3f in.”, beam_length);
sprintf(work, “Load Posit.: %.3f in.”, beam_point);
sprintf(work, “Load : %.3f lbs.”, beam_load);
/* Print Calculated Parameters */
sprintf(work, “Beam Cross Sectional Area in^2: %.3f”, beam_area);
sprintf(work, “Weight lbs.: %.3f”, beam_weight);
sprintf(work, “Axial Stiffness lb. / in: %.3g”, axial_stiffness);
sprintf(work, “Bending Stiffness lbs / in^2: %.3g”, bending_stiffness);
sprintf(work, “Maximum Beam Deflection in.: %.3g”, beam_deflect);
/* Draw cross section and loading diagrams */
* The global values of the beam parameters are use to calculate
* the other output variables of the beam parameters.
x_centroid = x_axis = beam_width / 2.0;
y_centroid = y_axis = beam_height / 2.0;
/* find moment of inertia for solid beam and later subtract
hollow sections for various beam types. */
moment_inertia = beam_width*beam_height*beam_height*beam_height/12.0;
beam_area = beam_thick*(2*beam_width + beam_height - 2*beam_thick);
moment_inertia = moment_inertia - (beam_width-beam_thick)*pow((beam_height-beam_thick), 3.0)/12.0;
if(beam_type == CHANNEL_BEAM) {
beam_area = beam_thick*(2*beam_width + beam_height - 2*beam_thick);
x_centroid =(pow(beam_width, 2.0) + (beam_height - 2*beam_thick)*beam_thick)/(beam_width + (beam_height - 2*beam_thick))/2.0;
moment_inertia = moment_inertia - (beam_width-beam_thick)*pow((beam_height-beam_thick), 3.0)/12.0;
beam_area = beam_width*beam_height;
if(beam_type == HOLLOW_BEAM) {
beam_area = beam_thick*(2*beam_width + 2*beam_height - 4*beam_thick);
moment_inertia = moment_inertia - (beam_width - 2*beam_thick)*pow((beam_height-beam_thick), 3.0)/12.0;
beam_area = beam_thick*(beam_width + beam_height - beam_thick);
x_centroid = (beam_width*beam_width +(beam_height-beam_thick)*beam_thick)/2.0/(beam_height + beam_width - beam_thick);
y_centroid = (beam_height*beam_height +(beam_width-beam_thick)*beam_thick)/2.0/(beam_height + beam_width - beam_thick);
moment_inertia = (beam_width*pow(y_centroid, 3.0) - (beam_width-beam_thick)*pow((y_centroid-beam_thick),3.0)+beam_thick*pow((beam_height-y_centroid), 3.0))/3.0;
axial_stiffness = beam_area * materials[beam_material].modulus;
bending_stiffness = materials[beam_material].modulus * moment_inertia;
beam_weight = beam_area * materials[beam_material].weight * beam_length;
/* find deflection of beam under loading */
deflect_point = pow((beam_point*(2 * beam_length-beam_point)/3.0), .5);
beam_deflect = beam_load*(beam_length - beam_point)/(3.0*bending_stiffness*beam_length)*pow(deflect_point, 3);
* User input functions are handled through this subroutine. These
* functions include numerical input and checking, watching function
* keys, and issuing proper feedback for executive control.
/* set flag for cursor movement */
/* Do boxes and prompts for current input */
box(x-.01, y+.045, x+.30, y-.015, GREEN, NEW);
text(INPUT_LEFT+2*DOUBLE_LINE_GAP, INPUT_TOP+4*DOUBLE_LINE_GAP, list[entry_number].name);
text(INPUT_LEFT+2*DOUBLE_LINE_GAP, INPUT_TOP+.05, list[entry_number].help1);
text(INPUT_LEFT+2*DOUBLE_LINE_GAP, INPUT_TOP+.08, list[entry_number].help2);
inpoff = textwidth(list[entry_number].name)/xmax+.01;
/* Loop while numbers are being entered */
text(INPUT_LEFT+inpoff+(count+1)/100.0, INPUT_TOP+.02, “_”);
/* screen for too many chars, and no control keys */
while((count < 12) && ((in = getch()) != ENTER) && (in != 0)) {
if(((in >= ‘0’) && (in <= ‘9’)) || (in == ‘.’) || ((in == ‘-’) && (count == 0))) {
/* update screen input line */
text(INPUT_LEFT+inpoff+count/100.0, INPUT_TOP+.02, work2);
text(INPUT_LEFT+inpoff+(count+1)/100.0, INPUT_TOP+.02, “_”);
text(INPUT_LEFT+inpoff+(count)/100.0, INPUT_TOP+.02, “_”);
/* beep in case of input error */
/* look for control and cursor keys */
if(in == DOWN_ARROW) up_down = DOWN;
if(in == UP_ARROW) up_down = UP;
if(printes() == ERROR) {error = PRINTER_ERROR;}
if(printer() == ERROR) {error = PRINTER_ERROR;}
/* Check for numerical input error */
if((count > 0) && (count < 12)) {
if(count == 12) error = ERROR;
/* Clear input box and indicate error if they have occured */
box(x-.01, y+.045, x+.30, y-.015, BLACK, NEW);
box(INPUT_LEFT, INPUT_BOTTOM, INPUT_RIGHT, INPUT_TOP, GREEN, UPDATE);
if((error == ERROR) || (error == PRINTER_ERROR)) {
text(INPUT_LEFT+2*DOUBLE_LINE_GAP, INPUT_BOTTOM-.05, “INPUT ERROR - (Hit any key to clear)”);
text(INPUT_LEFT+2*DOUBLE_LINE_GAP, INPUT_BOTTOM-.05, “PRINTER ERROR - (Hit any key to clear)”);
box(INPUT_LEFT, INPUT_BOTTOM, INPUT_RIGHT, INPUT_TOP, GREEN, UPDATE);
/* update to new menu choice */
entry_number = entry_number + up_down;
if(entry_number < 0) entry_number = 7;
if(entry_number > 7) entry_number = 0;
* This routine will prepare the screen and dump it to an EPSON type
* printer. This will not do the printing, but will use the routines
* PRINTES() to do the printing.
/* Do the time sort of thing */
/* Clear input boxes on current screen */
box(xx-.01, yy+.045, xx+.30, yy-.015, BLACK, NEW);
box(INPUT_LEFT-2*DOUBLE_LINE_GAP, INPUT_BOTTOM, INPUT_RIGHT+2*DOUBLE_LINE_GAP, INPUT_TOP-.15, BLUE, UPDATE);
box(INPUT_LEFT-2*DOUBLE_LINE_GAP, INPUT_BOTTOM, INPUT_RIGHT+2*DOUBLE_LINE_GAP, INPUT_TOP-.15, BLACK, NEW);
box(DOUBLE_LINE_GAP, 1 - DOUBLE_LINE_GAP, 1 - DOUBLE_LINE_GAP, DOUBLE_LINE_GAP, BLUE, NEW);
/* Add design date to screen */
text(INPUT_LEFT, INPUT_TOP-.05, “Design Date :”);
text(INPUT_LEFT, INPUT_TOP, asctime(times));
* This routine will copy the screen to an EPSON type
* printer. This will constitute a hard copy output. This routine was
* prepared with the help of a basic routine written by Peter Budgell and
* Bernard Julien. The basic operation is to read a pixel from the
static int x, y, z, count, bit, error;
if((error = ((int)(biosprint(2, 7, 0)) & ERROR_BIT)) == 0) {
for(y = 0; y < (int)xmax; y = y + 8) {
biosprint(0, (int)(2*(ymax+PAGE_OFFSET))%256, 0);
biosprint(0, (int)(2*(ymax+PAGE_OFFSET))/256, 0);
for(x = 0; x < PAGE_OFFSET; x++) {
for(x = (int)ymax; x > 0; x--) {
count = count + bit*(getpixel(y+z, x) != BLACK);
* This routine will use the previous input value to determine input
* validity, and update valid inputs. The value will be taken from
* the WORK string and then considered for the current input.
if(work[0] == 0) error = NO_ERROR;
if((entry_number == 0) && (i_result > 0) && (i_result < L_BEAM+2)) {
if(beam_type != i_result-1) error = REVISED;
if((entry_number == 1) && (i_result > 0) && (i_result < ALUMINUM+2)) {
if(beam_material != i_result-1) error = REVISED;
if((entry_number == 2) && (f_result > 0.025) && (f_result < beam_width/2) && (f_result < beam_height/2)) {
if(beam_thick != f_result) error = REVISED;
if((entry_number == 3) && (f_result > beam_thick*2.0) && (f_result < 60.0)) {
if(beam_height != f_result) error = REVISED;
if((entry_number == 4) && (f_result > beam_thick/2.0) && (f_result < 60.0)) {
if(beam_width != f_result) error = REVISED;
if((entry_number == 5) && (f_result > 0.0) && (f_result < 200.0) && (f_result >= beam_point)) {
if(beam_length != f_result) error = REVISED;
if((entry_number == 6) && (f_result >= 0.0) && (f_result <= beam_length)) {
if(beam_point != f_result) error = REVISED;
if((entry_number == 7) && (abs(f_result) < 10000000.0)) {
if(beam_load != f_result) error = REVISED;
void text(double x, double y, char *text)
* A routine to make text statements more readable, by allowing entry in
outtextxy(x * xmax, y * ymax, text);
void draw_line(double x1, double y1, double x2, double y2)
* A routine to simplify line statements by allowing normalized calls.
line((int)(x1*xmax), (int)(y1*ymax), (int)(x2*xmax), (int)(y2*ymax));
void box(double x1, double y1, double x2, double y2, int color, int refresh)
* This routine will simply draw a box with double lines , or erase
draw_line(x1 + DOUBLE_LINE_GAP, y1 - DOUBLE_LINE_GAP, x2 - DOUBLE_LINE_GAP, y1 - DOUBLE_LINE_GAP);
draw_line(x2 - DOUBLE_LINE_GAP, y1 - DOUBLE_LINE_GAP, x2 - DOUBLE_LINE_GAP, y2 + DOUBLE_LINE_GAP);
draw_line(x2 - DOUBLE_LINE_GAP, y2 + DOUBLE_LINE_GAP, x1 + DOUBLE_LINE_GAP, y2 + DOUBLE_LINE_GAP);
draw_line(x1 + DOUBLE_LINE_GAP, y2 + DOUBLE_LINE_GAP, x1 + DOUBLE_LINE_GAP, y1 - DOUBLE_LINE_GAP);
/* Erase box contents if flag set */
setfillstyle(SOLID_FILL, BLACK);
floodfill((int)(((x2 + x1)/2.0)*xmax), (int)(((y1 + y2)/2.0) * ymax), color);
* This section will produce all beam graphics and dimensions
x_s = xmax/2 + 3*EXTENSION + 40;
if(x_axis != x_centroid) y_e = y_e + EXTENSION;
if(y_axis == y_centroid) x_s = xmax/2 + 2*EXTENSION + 40;
scale_x = (x_e - x_s) / beam_height / X_Y_RATIO;
scale_y = (y_e - y_s) / beam_height;
if(beam_width >= beam_height){
scale_x = (x_e - x_s) / beam_width / X_Y_RATIO;
scale_y = (y_e - y_s) / beam_width;
cx2 = x_s + (int)(scale_x * beam_thick);
cx3 = x_s + (int)(scale_x * (beam_width - beam_thick) / 2);
cx4 = x_s + (int)(scale_x * (beam_width + beam_thick) / 2);
cx5 = x_s + (int)(scale_x * (beam_width - beam_thick));
cx6 = x_s + (int)(scale_x * beam_width);
cy2 = y_s + (int)(scale_y * beam_thick);
cy3 = y_s + (int)(scale_y * (beam_height - beam_thick) / 2);
cy4 = y_s + (int)(scale_y * (beam_height + beam_thick) / 2);
cy5 = y_s + (int)(scale_y * (beam_height - beam_thick));
cy6 = y_s + (int)(scale_y * beam_height);
x_c_offset = cx1 + scale_x * x_centroid;
y_c_offset = cy1 + scale_y * y_centroid;
x_offset = cx1 + scale_x * x_axis;
y_offset = cy1 + scale_y * y_axis;
{outtextxy(cx1 - EXTENSION, cy6 - 2*EXTENSION-15, “BEAM CROSS SECTION”);}
else {outtextxy(cx1 - EXTENSION, cy6 - EXTENSION-15, “BEAM CROSS SECTION”);}
/* Title for beam deflection */
text(.54, .76, “EXAGERATED BEAM DEFLECTION (simple supports)”);
if(draw_beam == CHANNEL_BEAM) {
if(draw_beam == HOLLOW_BEAM) {
/* Draw beam for bending display */
line((int)(.60*xmax), (int)(.90*ymax), (int)(.60*xmax), (int)(.88*ymax));
line((int)(.90*xmax), (int)(.90*ymax), (int)(.90*xmax), (int)(.88*ymax));
if(fabs(beam_deflect/beam_length) > 0.00001) {
de = beam_length/6.0*beam_deflect/fabs(beam_deflect);
for(px = 0.0; px <= deflect_point; px = px + beam_length/200){
py = ((de-de*pow(((deflect_point -px)/deflect_point), 2.0))/beam_length) * (.1) + .88;
putpixel((int)((.6+px/beam_length*.3)*xmax), (int)(py*ymax), CYAN);
putpixel((int)((.6+px/beam_length*.3)*xmax), (int)((py+.02)*ymax), CYAN);
for(px = deflect_point; px <= beam_length; px = px + beam_length/200){
py = ((de-de*pow(((px-deflect_point)/(beam_length - deflect_point)), 2.0))/beam_length) * (.1) + .88;
putpixel((int)((.6+px/beam_length*.3)*xmax), (int)(py*ymax), CYAN);
putpixel((int)((.6+px/beam_length*.3)*xmax), (int)((py+.02)*ymax), CYAN);
line((int)(.60*xmax), (int)(.90*ymax), (int)(.90*xmax), (int)(.90*ymax));
line((int)(.60*xmax), (int)(.88*ymax), (int)(.90*xmax), (int)(.88*ymax));
/* Fill Beam Cross section if thick enough */
setfillstyle(LTSLASH_FILL, 7+beam_material);
if(((cx2-cx1) > 2) && ((cy1 - cy2) > 2)){
floodfill(cx1 + 1, cy1 - 1, CYAN);
floodfill(cx1 + 1, cy6 + 1, CYAN);
line(xmax*.60, ymax*.90 + 3, xmax*.60, ymax*.90 + EXTENSION);
line(xmax*.90, ymax*.90 + 3, xmax*.90, ymax*.90 + EXTENSION);
line(xmax*.60, ymax*.90 + 10, xmax*.90, ymax*.90 + 10);
sprintf(work, “%.3f in.”, beam_length);
offset = .30 * (beam_point / beam_length) + .60;
line(xmax*.6, ymax*.88 - 3, xmax*.6, ymax*.88 - EXTENSION);
line(xmax*offset, ymax*.88 - 3, xmax*offset, ymax*.88 - EXTENSION);
line(xmax*.6, ymax*.88 - 10, xmax*offset, ymax*.88 - 10);
line(xmax*offset, ymax*.88 - 3, xmax*offset -3, ymax*.88 - 8);
line(xmax*offset, ymax*.88 - 3, xmax*offset +3, ymax*.88 - 8);
sprintf(work, “%.3f in.”, beam_point);
sprintf(work, “%.3f lb.”, beam_load);
line(cx1, cy1+3, cx1, cy1 + EXTENSION);
line(cx6, cy1+3, cx6, cy1 + EXTENSION);
line(cx1, cy1 + 10, cx6, cy1 + 10);
sprintf(work, “%.3f in.”, beam_width);
outtextxy(cx1 + 10, cy1+15, work);
/* Height and Thickness Dimensions */
settextstyle(SMALL_FONT, VERT_DIR, 4);
line(cx6+3, cy1, cx6+EXTENSION, cy1);
line(cx6+3, cy6, cx6+EXTENSION, cy6);
line(cx6+10, cy1, cx6+10, cy6);
sprintf(work, “%.3f in.”, beam_height);
outtextxy(cx6 + EXTENSION, cy1-10-textwidth(work), work);
/* Draw Thickness Dimension for all but solid beam */
line(cx1-EXTENSION, cy1, cx1-3, cy1);
line(cx1-EXTENSION, cy2, cx1-3, cy2);
line(cx1-10, cy1, cx1-10, cy1+15);
line(cx1-10, cy2, cx1-10, cy2-15);
sprintf(work, “%.3f in.”, beam_thick);
outtextxy(cx1-15, cy2-10-textwidth(work), work);
/* Principal and centroid y axis dimensions */
line(cx1-EXTENSION, cy1, cx1-2*EXTENSION, cy1);
line(cx1-EXTENSION-3, y_offset, cx1-2*EXTENSION, y_offset);
line(cx1-EXTENSION-10, cy1, cx1-EXTENSION-10, cy1+15);
line(cx1-EXTENSION-10, y_offset, cx1-EXTENSION-10, y_offset-15);
sprintf(work, “%.3f in.”, y_axis);
outtextxy(cx1-EXTENSION-15, y_offset-10-textwidth(work), work);
line(cx1-2*EXTENSION, cy1, cx1-3*EXTENSION, cy1);
line(cx1-2*EXTENSION-3, y_c_offset, cx1-3*EXTENSION, y_c_offset);
line(cx1-2*EXTENSION-10, cy1, cx1-2*EXTENSION-10, cy1+15);
line(cx1-2*EXTENSION-10, y_c_offset, cx1-2*EXTENSION-10, y_c_offset-15);
sprintf(work, “%.3f in.”, y_centroid);
outtextxy(cx1-2*EXTENSION-15, y_c_offset-10-textwidth(work), work);
settextstyle(SMALL_FONT, HORIZ_DIR, 4);
/* Principal and centroid x axis dimensions */
line(cx1, cy6-3, cx1, cy6 - EXTENSION);
line(x_offset, cy6-3, x_offset, cy6-EXTENSION);
line(cx1-EXTENSION, cy6-10, cx1, cy6-10);
line(x_offset, cy6-10, x_offset+EXTENSION, cy6-10);
sprintf(work, “%.3f in.”, x_axis);
outtextxy(x_offset + 10, cy6-EXTENSION, work);
line(cx1, cy6-EXTENSION-3, cx1, cy6 - 2*EXTENSION);
line(x_c_offset, cy6-EXTENSION-3, x_c_offset, cy6 - 2*EXTENSION);
line(cx1-EXTENSION, cy6-EXTENSION-10, cx1, cy6-EXTENSION-10);
line(x_c_offset, cy6-EXTENSION-10, x_c_offset+EXTENSION, cy6-EXTENSION-10);
sprintf(work, “%.3f in.”, x_centroid);
outtextxy(x_c_offset + 10, cy6 - 2*EXTENSION, work);
setlinestyle(CENTER_LINE, 0, NORM_WIDTH);
line(x_offset, cy1+5, x_offset, cy6-5);
line(cx1-5, y_offset, cx6+5, y_offset);
setlinestyle(DASHED_LINE, 0, NORM_WIDTH);
line(x_c_offset, cy1+5, x_c_offset, cy6-5);
line(cx1-5, y_c_offset, cx6+5, y_c_offset);
setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
* This will deinitialize the graphics routines initialized earlier.