static char sccsid[] = "@(#)xengine.c 1.9 9/19/90"; /* * xengine - reciprocating engine for X :-) * * Author: Kazuhiko Shutoh, 1990. * * Permission to use, copy, modify and distribute without charge this software, * documentation, images, etc. is granted, provided that this comment and the * author's name is retained. The author assumes no responsibility for lost * sleep as a consequence of use of this software. * * Send any comments, bug reports, etc. to: shutoh@isl.yamaha.JUNET or, for * oversea: shutoh%isl.yamaha.JUNET%kddlab@uunet.uu.net * */ #include #include #include #include #include #include #include #include #include #include "patchlevel.h" #define PI 3.141592654 XtCallbackProc redraw_callback(); XtTimerCallbackProc Cylcle(); Widget toplevel, base, rpm_info, engine; GC gcPiston, gcShaft, gcCylinder, gcRoter, gcBack, gcDep, gcPre, gcEngine; Pixmap enginePixmap; int width, height; String colors[] = {"gray", "lightseagreen", "dimgrey", "forestgreen", "black", "red", "cyan", "firebrick"}; main(argc, argv) int argc; char **argv; { Arg args[10]; XtTranslations newTranslations; static XtActionsRec redrawActions[] = { {"expose", (XtCallbackProc) redraw_callback}, }; static char *overrideTranslations = ": expose() \n\ : expose()"; XColor srcColor, dummyColor; int i; int count; XtTimerCallbackProc Cycle(); toplevel = XtInitialize("xengine", "XEngine", NULL, 0, &argc, argv); for (count = 1; count < argc; count++) { if ((strcmp("-piston", argv[count]) == 0) && (count + 1 <= argc)) strcpy(colors[0], argv[++count]); else if ((strcmp("-shaft", argv[count]) == 0) && (count + 1 <= argc)) strcpy(colors[1], argv[++count]); else if ((strcmp("-cylinder", argv[count]) == 0) && (count + 1 <= argc)) strcpy(colors[2], argv[++count]); else if ((strcmp("-roter", argv[count]) == 0) && (count + 1 <= argc)) strcpy(colors[3], argv[++count]); else if ((strcmp("-back", argv[count]) == 0) && (count + 1 <= argc)) strcpy(colors[4], argv[++count]); else if ((strcmp("-dep", argv[count]) == 0) && (count + 1 <= argc)) strcpy(colors[5], argv[++count]); else if ((strcmp("-pre", argv[count]) == 0) && (count + 1 <= argc)) strcpy(colors[6], argv[++count]); else if ((strcmp("-patchlevel", argv[count]) == 0) && (count + 1 <= argc)) { printf("xengine - written by Kazuhiko Shutoh\nSCCS ID : %s\nPatchlevel : %d\n", sccsid, PATCHLEVEL); exit(0); } else if ((strcmp("-mono", argv[count]) == 0) && (count + 1 <= argc)) { for (i = 0; i < 8; i++) strcpy(colors[i], "white"); strcpy(colors[4], "black"); } else { fprintf(stderr, "Usage : xengine [Toolkit-Options][-piston piston_color][-shaft shaft_color][-cylinder cylinder_color][-roter roter_color][-back background_color][-dep depression_colore][-pre pression color][-mono][-patchlevel]\n"); exit(0); } } base = XtCreateManagedWidget("base", formWidgetClass, toplevel, NULL, 0); i = 0; XtSetArg(args[i], XtNwidth, 200); i++; XtSetArg(args[i], XtNheight, 200); i++; engine = XtCreateManagedWidget("engine", boxWidgetClass, base, args, i); width = height = 200; i = 0; XtSetArg(args[i], XtNfromHoriz, engine); i++; XtSetArg(args[i], XtNheight, 200); i++; rpm_info = XtCreateManagedWidget("rpm_info", asciiTextWidgetClass, base, args, i); XtAddActions(redrawActions, XtNumber(redrawActions)); newTranslations = XtParseTranslationTable(overrideTranslations); XtOverrideTranslations(engine, newTranslations); XtRealizeWidget(toplevel); /* Get graphic context */ gcPiston = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL); XAllocNamedColor(XtDisplay(engine), DefaultColormap(XtDisplay(engine), 0), colors[0], &srcColor, &dummyColor); XSetForeground(XtDisplay(engine), gcPiston, srcColor.pixel); gcShaft = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL); XAllocNamedColor(XtDisplay(engine), DefaultColormap(XtDisplay(engine), 0), colors[1], &srcColor, &dummyColor); XSetForeground(XtDisplay(engine), gcShaft, srcColor.pixel); XSetLineAttributes(XtDisplay(engine), gcShaft, 2, LineSolid, CapButt, JoinMiter); gcCylinder = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL); XAllocNamedColor(XtDisplay(engine), DefaultColormap(XtDisplay(engine), 0), colors[2], &srcColor, &dummyColor); XSetForeground(XtDisplay(engine), gcCylinder, srcColor.pixel); gcRoter = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL); XAllocNamedColor(XtDisplay(engine), DefaultColormap(XtDisplay(engine), 0), colors[3], &srcColor, &dummyColor); XSetForeground(XtDisplay(engine), gcRoter, srcColor.pixel); gcBack = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL); XAllocNamedColor(XtDisplay(engine), DefaultColormap(XtDisplay(engine), 0), colors[4], &srcColor, &dummyColor); XSetForeground(XtDisplay(engine), gcBack, srcColor.pixel); gcDep = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL); XAllocNamedColor(XtDisplay(engine), DefaultColormap(XtDisplay(engine), 0), colors[5], &srcColor, &dummyColor); XSetForeground(XtDisplay(engine), gcDep, srcColor.pixel); gcPre = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL); XAllocNamedColor(XtDisplay(engine), DefaultColormap(XtDisplay(engine), 0), colors[6], &srcColor, &dummyColor); XSetForeground(XtDisplay(engine), gcPre, srcColor.pixel); gcEngine = XCreateGC(XtDisplay(engine), XtWindow(engine), (unsigned long) 0, NULL); XAllocNamedColor(XtDisplay(engine), DefaultColormap(XtDisplay(engine), 0), colors[7], &srcColor, &dummyColor); XSetForeground(XtDisplay(engine), gcEngine, srcColor.pixel); /* Create engine Pixmap */ enginePixmap = XCreatePixmap(XtDisplay(engine), XtWindow(engine), width, height, DefaultDepth(XtDisplay(engine), 0)); /* Interval timer start */ XtAddTimeOut(1, Cycle, NULL); XtMainLoop(); } XtCallbackProc redraw_callback(w, event, params, nparams) Widget w; XEvent *event; String *params; Cardinal *nparams; { Arg args[10]; XtSetArg(args[0], XtNwidth, 0); XtSetArg(args[1], XtNheight, 0); XtGetValues(w, args, 2); width = args[0].value; height = args[1].value; XFreePixmap(XtDisplay(engine), enginePixmap); enginePixmap = XCreatePixmap(XtDisplay(engine), XtWindow(engine), width, height, DefaultDepth(XtDisplay(engine), 0)); } XtTimerCallbackProc Cycle(client_data, id) caddr_t client_data; XtIntervalId id; { Arg args[10]; static char label[256]; char tmp_str[16]; static int i = 0; static int sample_count = 0; static double mean = 0.0; double DrawEngine(); if (i++ > 10) { sprintf(tmp_str, "%4.1f rpm\n", mean / 10.0); if (sample_count++ > 14) { strcpy(label, ""); sample_count = 0; } strcat(label, tmp_str); XtSetArg(args[0], XtNstring, label); XtSetValues(rpm_info, args, 1); i = 0; mean = 0.0; } mean += DrawEngine(); XtAddTimeOut(1, Cycle, NULL); } double DrawEngine() { double cycle; static int sw = 1; double angle, theta; double piston_x1, piston_y1; double piston_x2, piston_y2; struct timeval start, end; struct timezone dummy; sw ^= 1; XSync(XtDisplay(engine), 0); gettimeofday(&start, &dummy); for (angle = -180; angle < 180; angle += 18) { theta = angle * (PI / 180.0); piston_x1 = sin(theta) * (width * 0.1) + (width / 2); piston_y1 = cos(theta) * (height * 0.1) + (height * 0.7); piston_x2 = width / 2; piston_y2 = piston_y1 - (height * 0.3); /* Crear Window */ XFillRectangle(XtDisplay(engine), enginePixmap, gcBack, 0, 0, width, height); /* Draw heat sink */ XFillRectangle(XtDisplay(engine), enginePixmap, gcEngine, (int) (width * 0.35), (int) (height * 0.3), (int) (width * 0.3), (int) (height * 0.02)); XFillRectangle(XtDisplay(engine), enginePixmap, gcEngine, (int) (width * 0.35), (int) (height * 0.35), (int) (width * 0.3), (int) (height * 0.02)); XFillRectangle(XtDisplay(engine), enginePixmap, gcEngine, (int) (width * 0.35), (int) (height * 0.4), (int) (width * 0.3), (int) (height * 0.02)); /* Draw Cylinder */ XFillRectangle(XtDisplay(engine), enginePixmap, gcEngine, (int) (width * 0.42), (int) (height * 0.24), (int) (width * 0.16), (int) (height * 0.5)); XFillArc(XtDisplay(engine), enginePixmap, gcEngine, (int) (piston_x2 - (width * 0.15)), (int) ((height * 0.7) - (height * 0.15)), (int) (width * 0.3), (int) (height * 0.3), 0 * 64, 360 * 64); XFillArc(XtDisplay(engine), enginePixmap, gcBack, (int) (piston_x2 - (width * 0.14)), (int) ((height * 0.7) - (height * 0.14)), (int) (width * 0.28), (int) (height * 0.28), 0 * 64, 360 * 64); XFillRectangle(XtDisplay(engine), enginePixmap, gcBack, (int) (width * 0.43), (int) (height * 0.25), (int) (width * 0.14), (int) (height * 0.5)); /* Draw Gas */ if (sw != 0) { XFillRectangle(XtDisplay(engine), enginePixmap, gcPre, (int) (width * 0.435), (int) (height * 0.25), (int) (width * 0.13), (int) (piston_y2 - (height * 0.05) - (height * 0.26) + (height * 0.1))); } else { XFillRectangle(XtDisplay(engine), enginePixmap, gcDep, (int) (width * 0.435), (int) (height * 0.25), (int) (width * 0.13), (int) (piston_y2 - (height * 0.05) - (height * 0.26) + (height * 0.1))); } /* Draw Piston arm */ XDrawLine(XtDisplay(engine), enginePixmap, gcShaft, (int) piston_x1, (int) piston_y1, (int) piston_x2, (int) piston_y2); XDrawLine(XtDisplay(engine), enginePixmap, gcShaft, (int) piston_x1, (int) piston_y1, (int) piston_x2, (int) (height * 0.7)); /* Draw Piston & ring */ XFillRectangle(XtDisplay(engine), enginePixmap, gcPiston, (int) (width * 0.435), (int) (piston_y2 - (height * 0.05)), (int) (width * 0.13), (int) (height * 0.1)); XFillRectangle(XtDisplay(engine), enginePixmap, gcShaft, (int) (width * 0.435), (int) (piston_y2 - (height * 0.045)), (int) (width * 0.13), (int) (height * 0.01)); XFillArc(XtDisplay(engine), enginePixmap, gcShaft, (int) (piston_x2 - (width * 0.015)), (int) (piston_y2 - (height * 0.015)), (int) (width * 0.03), (int) (height * 0.03), 0, 360 * 64); /* Draw Roter */ XFillArc(XtDisplay(engine), enginePixmap, gcRoter, (int) (piston_x2 - (width * 0.1)), (int) ((height * 0.7) - (height * 0.1)), (int) (width * 0.2), (int) (height * 0.2), (int) (angle + 30) * 64, 120 * 64); XFillArc(XtDisplay(engine), enginePixmap, gcPiston, (int) (piston_x2 - (width * 0.025)), (int) ((height * 0.7) - (height * 0.025)), (int) (width * 0.05), (int) (height * 0.05), 0, 360 * 64); XCopyArea(XtDisplay(engine), enginePixmap, XtWindow(engine), gcCylinder, 0, 0, width, height, 0, 0); } XSync(XtDisplay(engine), 0); gettimeofday(&end, &dummy); cycle = 60 / ((double) ((end.tv_sec * 1000000 + end.tv_usec) - (start.tv_sec * 1000000 + start.tv_usec)) / 1000000); return (cycle); }