/*
 * xfancy_spiro.c -- This is a SPIROGRAPH.
 * 
 * A Spirograph contains a circular disc having notches inside. Inside this
 * circular disc another corcular disc with notches outside. This second disc
 * has a TYHE hole inside. So when we rotate the second disc inside the first
 * one it traces a path. This is shown here.
 * 
 * Try for the following values :
 * 
 * Radius of the outer circle :12 Radius of the inner circle : 7 Radius of the
 * Tyhe hole    : 5
 * 
 * Try the other combinations also. I found that by varying values of the first
 * two parameters by keeping thier difference same then the effects are very
 * good.
 * 
 * Compile instruction : cc xfancy_spiro.c -o xfancy_spiro
 * -I/usr/local/openwin/include -lxview -lolgx -lX11 -lm
 * -L/usr/local/openwin/lib
 * 
 * Execution: This program executes in the openwindows. Type xfancy_spiro at your
 * comand prompt.
 * 
 * If you find this program to be something exciting or any BUGS, please mail to
 * duggem@utdallas.edu
 * 
 * Thanks : For Kodela Sridhar and Tammana Prasad.V.R for their constant
 * encouragement in my work.
 * 
 * Duggempudi. Satyanarayana Reddy 
 * 2400 Waterview Parkway, #813 
 * Richardson, 
 * TX 75080
 * 
 * Disclaimer: THE AUTHOR TAKES NO RESPONSIBILITY OF ANY KIND EITHER IMPLICIT OR
 * EXPLICIT TO ANY CONSEQUENTIAL DAMAGES OR PROBLEMS YOU MAY GET AFTER USING
 * THIS SOURCE CODE. ALSO THE AUTHOR DOES NOT ASSURE ANY COMPATIBILITY OF
 * THIS SOURCE CODE TO ANY OF YOUR PURPOSES. THIS CODE IS PROVIDED ON AS IS
 * BASIS.
 * 
 * PERMISSION TO COPY AND DISTRIBUTE THIS SOURCE CODE IS HEREBY GRANTED TO ANY
 * ONE WHO WANTS TO DO SO AS LONG AS THE ACKNOWLEDGEMENTS AND DISCLAIMER ARE
 * RETAINED.  PERMISSION TO ALTER THIS SOURCE CODE IS ALSO GRANTED TO ALL,
 * BUT MUST INCLUDE THE STATEMENT THAT THE ORIGINAL WAS CHANGED IF ANYBODY
 * WANTS TO CHANGE THE CODE.
 * 
 *
 * P.S: The paths in the compile instruction may vary according to your system.
 *      So please change those include &/or the library paths.
 */


#include <stdio.h>
#include <math.h>
#include <X11/Xlib.h>

#include <xview/xview.h>
#include <xview/panel.h>
#include <xview/font.h>
#include <xview/notify.h>
#include <xview/canvas.h>

#define PI 3.141592654

Frame           frame;
Canvas          canvas;
Display        *dpy;
GC              gc;
Xv_Window       paint_window;

int             cnt, A = 1, B = 1, D = 1;

main(argc, argv)
	int             argc;
	char           *argv[];
{
	Panel           panel;
	Xv_Font         _font;
	XFontStruct    *font;
	void            adjust_speedA(), adjust_speedB(), adjust_speedC(), spirograph();
	extern void     exit();

	xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);


	frame = (Frame) xv_create(XV_NULL, FRAME,
		    FRAME_LABEL, "Fancy_Spirograph By Duggempudi. S. Reddy",
				  XV_WIDTH, 643,
				  XV_HEIGHT, 264,
				  FRAME_SHOW_RESIZE_CORNER, FALSE,
				  NULL);

	panel = (Panel) xv_create(frame, PANEL,
				  XV_X, 0,
				  XV_Y, 0,
				  XV_WIDTH, 382,
				  XV_HEIGHT, WIN_EXTEND_TO_EDGE,
				  NULL);

	xv_create(panel, PANEL_BUTTON,
		  XV_X, 15,
		  XV_Y, 7,
		  PANEL_LABEL_STRING, "Quit",
		  PANEL_NOTIFY_PROC, exit,
		  NULL);

	xv_create(panel, PANEL_SLIDER,
		  PANEL_LABEL_STRING, "Outer Circle Radius ",
		  XV_X, 15,
		  XV_Y, 48,
		  PANEL_MIN_VALUE, 1,
		  PANEL_MAX_VALUE, 75,
		  PANEL_SHOW_RANGE, TRUE,
		  PANEL_SLIDER_END_BOXES, TRUE,
		  PANEL_NOTIFY_PROC, adjust_speedA,
		  NULL);
	xv_create(panel, PANEL_SLIDER,
		  PANEL_LABEL_STRING, "Inner Circle Radius  ",
		  XV_X, 15,
		  XV_Y, 78,
		  PANEL_MIN_VALUE, 1,
		  PANEL_MAX_VALUE, 75,
		  PANEL_SHOW_RANGE, TRUE,
		  PANEL_SLIDER_END_BOXES, TRUE,
		  PANEL_NOTIFY_PROC, adjust_speedB,
		  NULL);
	xv_create(panel, PANEL_SLIDER,
		  PANEL_LABEL_STRING, "Tyhe Hole Radius     ",
		  XV_X, 15,
		  XV_Y, 108,
		  PANEL_MIN_VALUE, 1,
		  PANEL_MAX_VALUE, 30,
		  PANEL_SHOW_RANGE, TRUE,
		  PANEL_SLIDER_END_BOXES, TRUE,
		  PANEL_NOTIFY_PROC, adjust_speedC,
		  NULL);

	canvas = (Canvas) xv_create(frame, CANVAS,
				    XV_WIDTH, 264,
				    XV_HEIGHT, 264,
				    CANVAS_X_PAINT_WINDOW, TRUE,
				    CANVAS_RETAINED, FALSE,
				    NULL);

	paint_window = (Xv_Window) xv_get(canvas_paint_window(canvas), XV_XID);

	window_fit(frame);


	dpy = (Display *) xv_get(frame, XV_DISPLAY);
	_font = (Xv_Font) xv_find(frame, FONT,
				  FONT_NAME, "icon",
				  NULL);
	font = (XFontStruct *) xv_get(_font, FONT_INFO);

	gc = DefaultGC(dpy, DefaultScreen(dpy));

	xv_main_loop(frame);
}


void
adjust_speedA(item, value)
	Panel_item      item;
	int             value;
{
	A = value;
	if (A < 1)
		A = 1;
	spirograph();

}

void
adjust_speedB(item, value)
	Panel_item      item;
	int             value;
{
	B = value;
	if (B < 1)
		B = 1;
	spirograph();

}

void
adjust_speedC(item, value)
	Panel_item      item;
	int             value;
{
	D = value;
	if (D < 1)
		D = 1;
	spirograph();

}

void
spirograph()
{
	int             i, n, ptnumber, factor, height = 264, width = 264, a,
	                b, d;
	float           theta = 0, phi, thinc = PI * 0.02;
	XPoint          pt, temp;

	XClearWindow(dpy, paint_window);

	factor = height / 20;
	a = A * factor;		/* outer circle radius */
	b = B * factor;		/* inner disc radius */
	d = D * factor;		/* radius of tyhe hole in the disc */
	n = b / hcf(a, b);
	ptnumber = n * 100;
	temp.x = a - b + d + width / 2;
	temp.y = height / 2;


	for (i = 0; i < ptnumber; i++) {
		theta = theta + thinc;
		phi = theta * (a - b) / b;
		pt.x = ((a - b) * cos(theta) + d * cos(phi)) + width / 2;
		pt.y = ((a - b) * sin(theta) - d * sin(phi)) + height / 2;

		XDrawLine(dpy, paint_window, gc, temp.x, temp.y, pt.x, pt.y);

		temp = pt;
	}

}

hcf(i, j)
	int             i, j;
{
	int             remain;
	do {
		remain = i % j;
		i = j;
		j = remain;
	} while (remain != 0);
	return (i);
}
