[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference rusure::math

Title:Mathematics at DEC
Moderator:RUSURE::EDP
Created:Mon Feb 03 1986
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:2083
Total number of notes:14613

1468.0. "Klein bottle display" by ALLVAX::JROTH (I know he moves along the piers) Wed Jul 03 1991 12:30

    The next note contains a hack program that shows a rotating klein bottle.

    - Jim
T.RTitleUserPersonal
Name
DateLines
1468.1kleinbottle.cALLVAX::JROTHI know he moves along the piersWed Jul 03 1991 12:38327
/* 
 *  Double buffered wireframe display of rotating Klein bottle
 *
 *  Assumes 8 plane pseudocolor visual; click on window to exit.
 *
 *  Jim Roth, CAD/CAM Technology Center
 *    
 *  cc -o kleinbottle -O3 -f kleinbottle.c -lm -lX11
 *
 *  $ CC/PREC=SINGLE KLEINBOTTLE.C
 *  $ LINK KLEINBOTTLE,SYS$INPUT:/OPTION
 *  SYS$SHARE:VAXCRTL/SHARE
 *  SYS$SHARE:DECW$XLIBSHR/SHARE
 *  SYS$SHARE:DECW$DWTLIBSHR/SHARE
 *  $ EXIT
 */

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>

#include <stdio.h>
#include <math.h>

extern GC XCreateGC();

#define PI 3.1415926535897932384264338

#define NRAD 32
#define NWID 32

#define NPTS ((NRAD+1)*(NWID+1))
#define NLINES (2*(NRAD+1)*(NWID+1))

static float twopi = 2.0*PI;
static float rtd = 180.0/PI;
static float dtr = PI/180.0;

static float xpts[NPTS], ypts[NPTS], zpts[NPTS];
static long lintab[NLINES][2];

static XSegment segbuf[NLINES];

static int npts = 0;
static int nlines = 0;
static int nsubdiv = 0;

static int nrad = 32, nwid = 32;

create_bottle(float x[],
	      float y[],
	      float z[],
	      long lintab[][2])
{
    float a, c, s, d, t, u;
    float wx1, wy1, wx2, wy2;
    int i, j, i1, i2, j1, j2;
    float tfract, wfract;
    float radius;
    
    tfract = 1.0; /* fraction of turn to construct */
    wfract = 1.0; /* fraction of width to construct */
    radius = 0.3; /* ring radius */
    
    npts = 0;
    for (i = 0; i <= nrad; i++) {
	u = tfract*twopi*(float)i/(float)nrad;
	for (j = 0; j < nwid; j++) {
	    t = ((float)j-.5*(float)nwid)/(.5*(float)nwid);
	    t *= wfract*PI;
	    a = sin(t)*(cos(.5*u)+sin(.5*u)*cos(t))-2.0;
	    z[npts] = sin(t)*(-sin(.5*u)+cos(.5*u)*cos(t));
	    x[npts] = a*cos(u);
	    y[npts] = a*sin(u);
	    x[npts] *= radius;
	    y[npts] *= radius;
	    z[npts] *= radius;
	    npts++;
	}
    }

    nlines = 0;
    for (i1 = 0; i1 <= nrad; i1++) {
	i2 = i1+1;
	if (i2 > nrad) i2--;
	for (j1 = 0; j1 < nwid; j1++) {
	    j2 = j1+1;
	    if (j2 == nwid) j2--;
	    lintab[nlines][0] = nwid*i1+j1;
	    lintab[nlines++][1] = nwid*i1+j2;
	    lintab[nlines][0] = nwid*i1+j1;
	    lintab[nlines++][1] = nwid*i2+j1;
	}
    }
}

main()
{
    int status;
    Display *dpy;
    Window win;
    Colormap cmap;
    GC gc;
    XSetWindowAttributes xswa;
    XWindowAttributes xwa;
    char *display = NULL;
    char *geom = NULL;
    XEvent xev;
    XGCValues xgcv;
    int winW, winH, winX, winY;
    int winWidth, winHeight;
    int fg, bg;
    unsigned int planes[2];
    unsigned int pixels[1];
    unsigned int ncolors, nplanes;
    int i, j, k;
    float ai, aj;
    int borderW, pixDepth;
    Window root;
    float a, c, s, t, u;
    float ux1, uy1, ux2, uy2;
    int ipts;
    XColor color;
    XColor frame_0_colors[4], frame_1_colors[4];
    GC erase_0_gc, erase_1_gc;
    GC draw_0_gc, draw_1_gc;
    GC erase_gc, draw_gc;
    int mask_0, mask_1;
    int frame_to_write = 0;
    float d = 5.0;
    
    create_bottle(xpts, ypts, zpts, lintab);
    
    if (!(dpy = XOpenDisplay(display)))
	perror("Cannot open display\n");
    
    winW = 800;
    winH = 800;
    winX = (DisplayWidth(dpy, DefaultScreen(dpy)) - winW) >> 1;
    winY = (DisplayHeight(dpy, DefaultScreen(dpy)) - winH) >> 1;
    
    if (!(cmap = XDefaultColormap(dpy, DefaultScreen(dpy))))
	perror("can't get default colormap");
    
    nplanes = 2;
    ncolors = 1;
    status = XAllocColorCells(dpy, cmap, 0,
			      planes,
			      nplanes,
			      pixels,
			      ncolors);
    if (status == 0)
	perror("can't allocate color planes");
    
    color.pixel = pixels[0];
    color.red = color.green = color.blue = 0;
    color.flags = DoRed | DoGreen | DoBlue;
    XStoreColor(dpy, cmap, &color);
    
    color.pixel = pixels[0] | planes[0] | planes[1];
    color.red = color.green = color.blue = 65535;
    color.flags = DoRed | DoGreen | DoBlue;
    XStoreColor(dpy, cmap, &color);
    
    for (i = 0; i < 2; i++) {
	for (j = 0; j < 2; j++) {
	    frame_0_colors[i*2+j].pixel = pixels[0] |
		(i & 1 ? planes[0] : 0) |
		    (j & 1 ? planes[1] : 0);
	    frame_0_colors[i*2+j].red = i & 1 ? 65535 : 0;
	    frame_0_colors[i*2+j].green = i & 1 ? 65535 : 0;
	    frame_0_colors[i*2+j].blue = i & 1 ? 65535 : 0;
	    frame_0_colors[i*2+j].flags = DoRed | DoGreen | DoBlue;
	    
	    frame_1_colors[i*2+j].pixel = pixels[0] |
		(i & 1 ? planes[0] : 0) |
		    (j & 1 ? planes[1] : 0);
	    
	    frame_1_colors[i*2+j].red = j & 1 ? 65535 : 0;
	    frame_1_colors[i*2+j].green = j & 1 ? 65535 : 0;
	    frame_1_colors[i*2+j].blue = j & 1 ? 65535 : 0;
	    frame_1_colors[i*2+j].flags = DoRed | DoGreen | DoBlue;
	}
    }
    
    xswa.event_mask = 0;
    xswa.background_pixel = pixels[0];
    xswa.border_pixel = pixels[0] | planes[0] | planes[1];
    xswa.event_mask = ButtonPressMask;
    
    win = XCreateWindow(dpy, DefaultRootWindow(dpy), 
			winX, winY, winW, winH, 0, 
			DefaultDepth(dpy, DefaultScreen(dpy)), 
			InputOutput, DefaultVisual(dpy, DefaultScreen(dpy)),
			CWEventMask | CWBackPixel | CWBorderPixel, &xswa);
    
    XChangeProperty(dpy, win, XA_WM_NAME, XA_STRING, 8,
		    PropModeReplace, "Klein Bottle", 12);
    
    mask_0 = ~(planes[1]);
    mask_1 = ~(planes[0]);
    
    erase_0_gc = XCreateGC(dpy, win, 0, NULL);
    XSetForeground(dpy, erase_0_gc, pixels[0]);
    XSetBackground(dpy, erase_0_gc, pixels[0]);
    XSetPlaneMask(dpy, erase_0_gc, mask_0);
    XSetFunction(dpy, erase_0_gc, GXcopy);
    
    erase_1_gc = XCreateGC(dpy, win, 0, NULL);
    XSetForeground(dpy, erase_1_gc, pixels[0]);
    XSetBackground(dpy, erase_1_gc, pixels[0]);
    XSetPlaneMask(dpy, erase_1_gc, mask_1);
    XSetFunction(dpy, erase_1_gc, GXcopy);
    
    draw_0_gc = XCreateGC(dpy, win, 0, NULL);
    XSetBackground(dpy, draw_0_gc, pixels[0]);
    XSetPlaneMask(dpy, draw_0_gc, mask_0);
    XSetFunction(dpy, draw_0_gc, GXcopy);
    
    draw_1_gc = XCreateGC(dpy, win, 0, NULL);
    XSetBackground(dpy, draw_1_gc, pixels[0]);
    XSetPlaneMask(dpy, draw_1_gc, mask_1);
    XSetFunction(dpy, draw_1_gc, GXcopy);
    
    XMapWindow(dpy, win);
    if (XGetWindowAttributes(dpy,win,&xwa)==0)
	perror("can't get window attributes (size)");
    
    winWidth = xwa.width;
    winHeight = xwa.height;
    
    XSetWindowColormap(dpy, win, cmap);
    
    XGetGeometry(dpy, win, &root,
		 &winX, &winY, &winW, &winH, &borderW, &pixDepth);
    
    c = cos(5.0*dtr);
    s = sin(5.0*dtr);
    
    for (i = 0; i < npts; i++) {
	t =       ypts[i]*c - zpts[i]*s;
	zpts[i] = ypts[i]*s + zpts[i]*c;
	ypts[i] = t;
    }
    
    frame_to_write = 0;
    
    XStoreColors(dpy, cmap, frame_0_colors, 4);
    
    XFillRectangle(dpy, win, erase_0_gc, 0, 0, winW, winH);
    XFillRectangle(dpy, win, erase_1_gc, 0, 0, winW, winH);
    
    XSync(dpy, 0);
    
 loop:
{
   XEvent event;

    while (XPending(dpy)) {
        XNextEvent(dpy, &event);
        if (event.type == ButtonPress)
            exit(0);
    }
}

{
    float c, s;
    
    if (frame_to_write) {
	fg = pixels[0] | planes[1];
	XSetForeground(dpy, draw_1_gc, fg);
	erase_gc = erase_1_gc;
	draw_gc = draw_1_gc;
    }
    else {
	fg = pixels[0] | planes[0];
	XSetForeground(dpy, draw_0_gc, fg);
	erase_gc = erase_0_gc;
	draw_gc = draw_0_gc;
    }
    
    c = cos(6.5*dtr);
    s = sin(6.5*dtr);
    for (i = 0; i < npts; i++) {
	t =       xpts[i]*c - zpts[i]*s;
	zpts[i] = xpts[i]*s + zpts[i]*c;
	xpts[i] = t;
    }

    c = cos(5.5*dtr);
    s = sin(5.5*dtr);
    for (i = 0; i < npts; i++) {
	t =       ypts[i]*c - zpts[i]*s;
	zpts[i] = ypts[i]*s + zpts[i]*c;
	ypts[i] = t;
    }

    d = 4.0;    
    for (i = 0; i < nlines; i++) {
	float ux1 = d/(d+zpts[lintab[i][0]])*(xpts[lintab[i][0]]);
	float uy1 = d/(d+zpts[lintab[i][0]])*(ypts[lintab[i][0]]);
	float ux2 = d/(d+zpts[lintab[i][1]])*(xpts[lintab[i][1]]);
	float uy2 = d/(d+zpts[lintab[i][1]])*(ypts[lintab[i][1]]);
	segbuf[i].x1 = winX+winW*(0.5+0.5*ux1);
	segbuf[i].y1 = winY+winH*(0.5+0.5*uy1);
	segbuf[i].x2 = winX+winW*(0.5+0.5*ux2);
	segbuf[i].y2 = winY+winH*(0.5+0.5*uy2);
    }
    
    if (frame_to_write) {
	XStoreColors(dpy, cmap, frame_0_colors, 4);
    }
    else {
	XStoreColors(dpy, cmap, frame_1_colors, 4);
    }
    
    frame_to_write = 1-frame_to_write;
    
    XFillRectangle(dpy, win, erase_gc, 0, 0, winW, winH);
    
    for (i = 0; i < nlines; i+= 4096) {
	int n = nlines-i > 4096 ? 4096 : nlines-i;
	XDrawSegments(dpy, win, draw_gc, &segbuf[i], n);
    }
}
goto loop;
}
1468.2question on compiling the klein bottle programSMAUG::ABBASIWed Jul 03 1991 15:133
    Jim, how do you change the include <x11/xlib> etc.. to compile on VMS?
    these are un*x path name. this will not compile on VMS as is.
    thanks.
1468.3Sample mappingVMSDEV::HALLYBThe Smart Money was on GoliathWed Jul 03 1991 15:533
    <X11/Xlib.h>	==>	"DECW$INCLUDE:XLIB"
    
    etc.
1468.4GUESS::DERAMOduly notedWed Jul 03 1991 17:467
        Or, use
        
        	$ define X11 decw$include
        
        (or define/user) before compiling.
        
        Dan
1468.5questionSMAUG::ABBASIWed Jul 03 1991 20:045
    anyone got this to run and produce something? I run it and get
    the window up, with kelvin bottle title at the top left corner
    and that is, screen stays blank!
    regards,
    /nasser
1468.6GUESS::DERAMOduly notedWed Jul 03 1991 20:533
        It works for me. (RISC ULTRIX V4.0)
        
        Dan
1468.7ELIS::GARSONV+F = E+2Fri Jul 05 1991 09:321
    It works for me. (VAXstation 3100, VMS)
1468.8.ps file of thisSTAR::ABBASIi think iam psychicFri Mar 05 1993 04:558
    i got a really neat picture of this from mathematica, i have it as
    .ps file, if you want the file to print it at your printer to see
    this, just send mail to me with subject "Send Klein" and the klein.ps
    file will be mailed to you..
    
    
    \bye
    \nasser