home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume18
/
gl_plot
/
part06
< prev
next >
Wrap
Text File
|
1989-03-23
|
43KB
|
1,433 lines
Subject: v18i064: GL Graphics Library for AT-clone Unix, Part06/07
Newsgroups: comp.sources.unix
Sender: sources
Approved: rsalz@uunet.UU.NET
Submitted-by: umix!m-net!dtlewis!lewis
Posting-number: Volume 18, Issue 64
Archive-name: gl_plot/part06
# To recover, type "sh archive"
echo restoring config.h
sed 's/^X//' > config.h <<XxX--EOF--XxX
X/* @(#) config.h 5.1 89/02/20 */
X/*
X * Copyright (c) David T. Lewis 1987, 1988
X * All rights reserved.
X *
X * Permission is granted to use this for any personal noncommercial use.
X * You may not distribute source or executable code for profit, nor
X * may you distribute it with a commercial product without the written
X * consent of the author. Please send modifications to the author for
X * inclusion in updates to the program. Thanks.
X */
X
X/* User modifiable parameters for GL graphics library. */
X/* ===> BEGIN USER MODIFIABLE PARAMETERS <=== */
X
X/* Select one of the following to specify your target system (Xenix */
X/* cross compile to MS_DOS should select MS_DOS). */
X
X#define SVAT 1
X#define XENIX_286 0
X#define MS_DOS 0
X#define UNIX_386 0 /* (not yet supported) */
X#define XENIX_386 0 /* (not yet supported) */
X
X/* If you defined MS_DOS 1, then specify your compiler here. */
X
X#if MS_DOS
X#define XEN2DOS 1 /* Compile on Xenix 286 for DOS target system */
X#define USOFT 0 /* Microsoft C under DOS */
X#define TCC 0 /* Borland Turbo-C */
X#define MIX_C 0 /* The old CP/M derived MIX-C compiler */
X#endif /* MS_DOS */
X
X/* The following should be defined if you do NOT have a numeric */
X/* coprocessor. It will cause some trig functions to be done with */
X/* integer math (see trig.c). */
X
X#define NOFLOAT 1
X
X/* The following should be defined if you want the gl library to handle */
X/* interrupt signals. This will clear the screen and return to text */
X/* mode when the interrupt key (or ^C, for MS-DOS) is pressed. If you */
X/* need to do your own signal routine (to close files, for example), */
X/* you may prefer not to have this defined. */
X
X#define DO_CLEANUP 1
X
X/* VIDEO stuff: */
X
X/* Define the name of the program or shell script which will be used */
X/* to switch video modes (UNIX only). This will be made from either */
X/* the mode.c program, or the mode.sh shell script, or some equivalent */
X/* program that works with your system and video adapter. */
X
X#define MODEPROG "mode"
X/* Another possible choice: */
X/* #define MODEPROG "/usr/local/bin/mode" */
X
X/* Define the name of the environment variable that you wish to use to */
X/* indicate your default graphics mode. If we call g_init(ENV_MODE), */
X/* then we will use this environment variable to set the graphics mode. */
X
X#define GL_ENV_MODE "GLMODE"
X
X/* If the environment variable is not set, then fall back to */
X/* DEFAULT_MODE as a last resort. Mode 4 is CGA color mode, a safe */
X/* choice for most systems. */
X
X#define DEFAULT_MODE 4
X
X/* PRINTER stuff: */
X
X/* Define name of the environment variable that you wish to set to */
X/* indicate your default print device. */
X
X#define GL_PLOT_DEV "PLOTDEV"
X
X/* For MS-DOS, define your printer device name (and ignore the rest */
X/* of the printer stuff that follows). Note: Microsoft compilers will */
X/* send output to "stdprn" regardless of how you define this; other */
X/* compilers will use the device you define below. See code in */
X/* g_finish.c if you need to change this. */
X
X#define DOSPRINTER "PRN:"
X
X/* Define the standard print spooler program for your system (UNIX). */
X
X#define PRINTPROG "/usr/bin/lp"
X#define LP_DEV_FLAG "-d"
X
X/* Define the device to use if GL_PLOT_DEV is not set. */
X/* Note: Use "lp" only if you plan to manually put the printer */
X/* driver in transparency mode (see lpset(1M)). */
X/* On Microport, your printer devices might look something like the */
X/* following, where /dev/lp is the standard printer driver, and */
X/* /dev/lpt is the transparency mode printer driver. See the "Readme" */
X/* file for more information. */
X/* */
X/* \$ ls -li /dev/lp* */
X/* 82 crw-rw-rw- 2 root sys 7, 0 Oct 9 18:03 /dev/lp */
X/* 82 crw-rw-rw- 2 root sys 7, 0 Oct 9 18:03 /dev/lp0 */
X/* 83 crw-rw-rw- 1 root sys 7, 1 Feb 11 1988 /dev/lp1 */
X/* 295 crw-rw-rw- 2 root sys 7,128 Oct 9 18:08 /dev/lpt */
X/* 295 crw-rw-rw- 2 root sys 7,128 Oct 9 18:08 /dev/lpt0 */
X/* 291 crw-rw-rw- 1 root sys 7,129 May 22 18:42 /dev/lpt1 */
X
X#define PRINTDEV "lpt"
X
X/* You may need to tweak the following in order to get round circles. */
X
X#define HERC_ASPECT_RATIO 0.7
X#define CGA_ASPECT_RATIO 0.85
X#define EGA_ASPECT_RATIO 0.6
X#define IBM_PR_ASPECT_RATIO 0.7
X#define LJ_PR_ASPECT_RATIO 0.81
X
X/* For Xenix System V 286, you must indicate the video adapter you */
X/* are using. Microport users can ignore this (they must, however, */
X/* create a shared memory key with shmcreate(1). MS-DOS users may */
X/* also ignore this. */
X
X#define GL_CGA 0
X#define GL_EGA 1
X#define GL_HERC 0
X#define GL_PGA 0 /* (not implemented) */
X#define GL_VGA 0 /* (easy to do, but not implemented) */
X
X/* The following definitions specify the shared memory key identifiers */
X/* which are used by Microport System V/AT. You are free to use any */
X/* identifiers you want to map to video memory with shmcreate(1). */
X/* The following are the recommended values. If you use these, the */
X/* key values will be the same as the physical memory addresses. */
X/* Change these definitions only if you are using different shared */
X/* memory keys for your system. Xenix users may ignore this. */
X
X#define MCA_KEY 0xB0000L
X#define CGA_KEY 0xB8000L
X#define HERC_P0KEY 0xB0000L
X#define HERC_P1KEY 0xB8000L
X#define EGA_KEY 0xA0000L
X
X/* ===> END USER MODIFIABLE PARAMETERS <=== */
X
X/* The following definitions specify the physical memory locations of */
X/* video memory, for use with MS-DOS. */
X
X#define DOS_MCA 0xB0000000L
X#define DOS_CGA 0xB8000000L
X#define DOS_H_P0 0xB0000000L
X#define DOS_H_P1 0xB8000000L
X#define DOS_EGA 0xA0000000L
X
X/* Some specific system dependent characteristics. */
X
X#if MIX_C
X#define HAS_SIG 0 /* System does not have ^C interrupt handling */
X#else
X#if USOFT
X#define HAS_SIG 0 /* System does not have ^C interrupt handling */
X#else
X#if XEN2DOS
X#define HAS_SIG 0 /* System does not have ^C interrupt handling */
X#else
X#define HAS_SIG 1 /* System has ^C interrupt handling */
X#endif /* XEN2DOS */
X#endif /* USOFT */
X#endif /* MIX_C */
X
X#if MIX_C
X#define HAS_ENV 0 /* System does not have getenv() call */
X#else
X#define HAS_ENV 1 /* System has getenv() call */
X#endif /* MIX_C */
X
X#if MS_DOS
X#define HAS_PIPES 0 /* System does not have popen() call */
X#else
X#define HAS_PIPES 1 /* System has popen() call */
X#endif /* MS_DOS */
X
X#if USOFT
X#define HAS_SLEEP 0 /* System does not have sleep() call */
X#else
X#if XEN2DOS
X#define HAS_SLEEP 0 /* System does not have sleep() call */
X#else
X#if MIX_C
X#define HAS_SLEEP 0 /* System does not have sleep() call */
X#else
X#define HAS_SLEEP 1 /* System has sleep() call */
X#endif /* MIX_C */
X#endif /* XEN2DOS */
X#endif /* USOFT */
X
X#if MIX_C
X#define HAS_FMOD 0 /* System does not have fmod() call */
X#else
X#define HAS_FMOD 1 /* System has fmod() call */
X#endif /* MIX_C */
X
X#if MIX_C
X#define HAS_ATAN2 0 /* System does not have atan2() call */
X#else
X#define HAS_ATAN2 1 /* System has atan2() call */
X#endif /* MIX_C */
X
X/* Some MS-DOS compilers have "stdprn" predefined for stream output to */
X/* the printer. */
X
X#if USOFT
X#define HAS_STDPRN 1
X#else
X#if XEN2DOS
X#define HAS_STDPRN 1
X#else
X#if TCC
X#define HAS_STDPRN 1
X#else /* "stdprn" is not predefined */
X#define HAS_STDPRN 0
X#endif /* TCC */
X#endif /* XEN2DOS */
X#endif /* USOFT */
X
X/* The following should be defined for 286 versions, in which an */
X/* integer is 16 bits. Other machines must do extra work to check */
X/* for out of range on the normalized 2-D screen space (0 through */
X/* 32767). */
X
X#if MS_DOS
X#else
X#if XENIX_286
X#else
X#if SVAT
X#define INT16 1
X#else /* Not a 16 bit integer machine */
X#define INT16 0
X#endif /* SVAT */
X#endif /* XENIX_286 */
X#endif /* MS_DOS */
X
X/* Parameter to signal call is system dependent. Define a macro to */
X/* handle the difference between pointer to void and pointer to int. */
X
X#if TCC
X#define SIG_TYPE void
X#else
X#define SIG_TYPE int
X#endif /* TCC */
X
X/* Some compilers can use a macro for the calculation for transform */
X/* from normalized 2-D to screen coordinates. If yours can't, then */
X/* define N_TO_P_MACRO as 0. */
X/* (All the compilers I've tried are working now with the macro. Leave */
X/* this here just in case...) */
X
X#define N_TO_P_MACRO 1
X
X/* Compiler specific stuff for MS-DOS. */
X
X/* For MS-DOS, use the DO_BIOS macro to point to the library routine */
X/* that invokes a BIOS call. Int is the interrupt number, and reg */
X/* is a pointer to a structure representing machine registers. */
X/* Define REGISTERS as the name of the data structure for machine */
X/* registers (probably declared in <stdlib.h>). */
X/* The remaining macros (AL, AH ...) specify individual registers */
X/* within the REGISTERS data structure, as they would be referenced */
X/* in a REGISTERS structure (e.g. "inreg.AH"). */
X
X#if MIX_C
X#define DO_BIOS(int,inreg,outreg) bios(int,inreg)
X#define REGISTERS REGS
X#define AL byte.al
X#define AH byte.ah
X#define BL byte.bl
X#define BH byte.bh
X#define CL byte.cl
X#define CH byte.ch
X#define DL byte.dl
X#define DH byte.dh
X#endif /* MIX_C */
X
X#if USOFT
X#define DO_BIOS(int,inreg,outreg) int86(int,inreg,outreg)
X#define REGISTERS union REGS
X#define AL h.al
X#define AH h.ah
X#define BL h.bl
X#define BH h.bh
X#define CL h.cl
X#define CH h.ch
X#define DL h.dl
X#define DH h.dh
X#endif /* USOFT */
X
X#if XEN2DOS
X#define DO_BIOS(int,inreg,outreg) int86(int,inreg,outreg)
X#define REGISTERS union REGS
X#define AL h.al
X#define AH h.ah
X#define BL h.bl
X#define BH h.bh
X#define CL h.cl
X#define CH h.ch
X#define DL h.dl
X#define DH h.dh
X#endif /* XEN2DOS */
X
X#if TCC
X#define DO_BIOS(int,inreg,outreg) int86(int,inreg,outreg)
X#define REGISTERS union REGS
X#define AL h.al
X#define AH h.ah
X#define BL h.bl
X#define BH h.bh
X#define CL h.cl
X#define CH h.ch
X#define DL h.dl
X#define DH h.dh
X#endif /* TCC */
X
XxX--EOF--XxX
echo restoring g_fntctl.c
sed 's/^X//' > g_fntctl.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) g_fntctl.c 5.1 89/02/20";
X#endif
X
X/*
X * Copyright (c) David T. Lewis 1988
X * All rights reserved.
X *
X * Permission is granted to use this for any personal noncommercial use.
X * You may not distribute source or executable code for profit, nor
X * may you distribute it with a commercial product without the written
X * consent of the author. Please send modifications to the author for
X * inclusion in updates to the program. Thanks.
X */
X
X/* Control size, aspect ratio, spacing, angle and slant of stroke font. */
X/* Size, aspect ratio and spacing control height, relative width and */
X/* relative spacing of characters, with 1.0 selecting default values. */
X/* Changing size will change the width and spacing appropriately. */
X/* Changing width will change the spacing. */
X/* Angle is the angle of a text string in radians, with positive */
X/* values rotating the text clockwise. Slant is the character slant */
X/* in radians (typically a number on the order of 0.2), with positive */
X/* values slanting the text to the "right," as in italics. */
X
X#include "config.h"
X#include "bitmaps.h"
X#include "graphics.h"
X
Xextern struct GL_graphics graphics;
X
Xint g_fontctl(size, aspect_ratio, spacing, angle, slant)
Xfloat size, aspect_ratio, spacing, angle, slant;
X
X{
X graphics.strokefont.xtic
X = (int)(size * aspect_ratio * spacing *
X (float)graphics.default_strokefont.xtic);
X graphics.strokefont.ytic
X = (int)(size * (float)graphics.default_strokefont.ytic);
X graphics.strokefont.xsize
X = (int)(size * aspect_ratio *
X (float)graphics.default_strokefont.xsize);
X graphics.strokefont.ysize
X = (int)(size * (float)graphics.default_strokefont.ysize);
X graphics.strokefont.angle = angle;
X graphics.strokefont.slant = slant;
X
X if (angle == 0.0) graphics.strokefont.angle_flag = FALSE;
X else graphics.strokefont.angle_flag = TRUE;
X
X if (slant == 0.0) graphics.strokefont.slant_flag = FALSE;
X else graphics.strokefont.slant_flag = TRUE;
X
X return(0);
X}
X
XxX--EOF--XxX
echo restoring gf_types.h
sed 's/^X//' > gf_types.h <<XxX--EOF--XxX
X/****** Warning! Do not alter this file without updating gl.h! *******/
X
X/* @(#) gf_types.h 5.1 89/02/20 */
X/*
X * Copyright (c) David T. Lewis 1988
X * All rights reserved.
X *
X * Permission is granted to use this for any personal noncommercial use.
X * You may not distribute source or executable code for profit, nor
X * may you distribute it with a commercial product without the written
X * consent of the author. Please send modifications to the author for
X * inclusion in updates to the program. Thanks.
X */
X
X/* Definition(s) required for more than one include file.
X */
X
X/* Define pixel setting modes. */
X
X#define CLEAR 0
X#define AND 1
X#define OR 2
X#define XOR 3
X
X/* Define colors. */
X
X#define BLACK 0
X#define BLUE 1
X#define GREEN 2
X#define CYAN 3
X#define RED 4
X#define MAGENTA 5
X#define BROWN 6
X#define WHITE 7
X#define GREY 8
X#define LT_BLUE 9
X#define LT_GREEN 10
X#define LT_CYAN 11
X#define LT_RED 12
X#define LT_MAGENTA 13
X#define YELLOW 14
X#define LT_WHITE 15
X
X/* Define line styles (not yet implemented). */
X
X#define SOLID 0xffffffffL /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
X#define DOTTED 0x66666666L /* XX..XX..XX..XX..XX..XX..XX..XX.. */
X#define DASHED 0xffe0ffe0L /* XXXXXXXXXXX.....XXXXXXXXXXX..... */
X#define SHORTDASHED 0xf8f8f8f8L /* XXXXX...XXXXX...XXXXX...XXXXX... */
X#define LONGDASHED 0xffffff00L /* XXXXXXXXXXXXXXXXXXXXXXXX........ */
X#define DOTDASHED 0xfc30fc30L /* XXXXXX....XX....XXXXXX....XX.... */
X
X/* Define line weights (not yet implemented). */
X
X#define LIGHT 1
X#define MEDIUM 2
X#define HEAVY 4
X
X
XxX--EOF--XxX
echo restoring gl.h
sed 's/^X//' > gl.h <<XxX--EOF--XxX
X/* @(#) gl.h 5.1 89/02/20 */
X/*
X * Copyright (c) David T. Lewis 1988
X * All rights reserved.
X *
X * Permission is granted to use this for any personal noncommercial use.
X * You may not distribute source or executable code for profit, nor
X * may you distribute it with a commercial product without the written
X * consent of the author. Please send modifications to the author for
X * inclusion in updates to the program. Thanks.
X */
X
X/* This file defines the interface to the graphics library, and should
X * be included in user programs.
X */
X
X/* Definition of programming interface to gl library. */
X
Xextern int g_clear();
Xextern int g_init();
Xextern int g_finish();
Xextern int g_pix_mode();
Xextern int g_pix_color();
Xextern int g_fontctl();
Xextern long g_style();
Xextern int g_weight();
Xextern int p_wr_pix();
Xextern int c_cellchar();
Xextern int c_cellstr();
Xextern int c_cursor();
Xextern int n_movepen();
Xextern int n_box();
Xextern int n_line();
Xextern int n_draw();
Xextern int n_grafchar();
Xextern int n_grafstr();
Xextern int n_arc();
Xextern int n_ellipse();
Xextern int n_point();
X
X/* Everything that follows should be identical to gf_types.h and modes.h. */
X
X/* @(#) gf_types.h 1.4 88/12/26 */
X
X/* Define pixel setting modes. */
X
X#define CLEAR 0
X#define AND 1
X#define OR 2
X#define XOR 3
X
X/* Define colors. */
X
X#define BLACK 0
X#define BLUE 1
X#define GREEN 2
X#define CYAN 3
X#define RED 4
X#define MAGENTA 5
X#define BROWN 6
X#define WHITE 7
X#define GREY 8
X#define LT_BLUE 9
X#define LT_GREEN 10
X#define LT_CYAN 11
X#define LT_RED 12
X#define LT_MAGENTA 13
X#define YELLOW 14
X#define LT_WHITE 15
X
X/* Define line styles. */
X
X#define SOLID 0xffffffffL /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
X#define DOTTED 0x66666666L /* XX..XX..XX..XX..XX..XX..XX..XX.. */
X#define DASHED 0xffe0ffe0L /* XXXXXXXXXXX.....XXXXXXXXXXX..... */
X#define SHORTDASHED 0xf8f8f8f8L /* XXXXX...XXXXX...XXXXX...XXXXX... */
X#define LONGDASHED 0xffffff00L /* XXXXXXXXXXXXXXXXXXXXXXXX........ */
X#define DOTDASHED 0xfc30fc30L /* XXXXXX....XX....XXXXXX....XX.... */
X
X/* Define line weights (not yet implemented). */
X
X#define LIGHT 1
X#define MEDIUM 2
X#define HEAVY 4
X
X/* @(#) modes.h 1.4 89/01/10 */
X
X/*
X * Mode definitions. These will be used by init(), and by the mode
X * program or shell script. As much as possible, the numeric mode
X * values should correspond to those used by the uPort screen driver
X * and by DOS. The values given for hercules and for printers are
X * arbitrary, but should not conflict with other "standard" assignments.
X */
X
X/* ENV_MODE means take the mode setting from an environment variable. */
X#define ENV_MODE 0
X
X/* CGA text modes */
X#define MONO_TEXT 0x02
X#define COLOR_TEXT 0x03
X
X/* CGA modes (for CGA or EGA) */
X#define CGA_COLOR_MODE 0x04
X#define CGA_HI_RES_MODE 0x06
X
X/* Monochrome text mode */
X#define MDA_TEXT 0x07
X
X/* Hercules mono graphics, page 0 and page 1 */
X/* Note: Modes 8 and 9 were used by the IBM PC Junior. I trust that */
X/* they will not be found on your machine. */
X#define HERC_P0_MODE 0x08
X#define HERC_P1_MODE 0x09
X
X/* EGA 640 x 350 color mode */
X#define EGA_COLOR_MODE 0x010
X
X/* Anything beyond MAXVIDEO is not a video board. Printers and other */
X/* hardcopy would fall in this category. */
X
X#define MAXVIDEO 0x0FF
X
X/* Non-video modes follow. */
X
X#define IBM_PRINTER 0x100
X
X
XxX--EOF--XxX
echo restoring modes.h
sed 's/^X//' > modes.h <<XxX--EOF--XxX
X/****** Warning! Do not alter this file without updating gl.h! *******/
X
X/* @(#) modes.h 5.1 89/02/20 */
X/*
X * Copyright (c) David T. Lewis 1987, 1988
X * All rights reserved.
X *
X * Permission is granted to use this for any personal noncommercial use.
X * You may not distribute source or executable code for profit, nor
X * may you distribute it with a commercial product without the written
X * consent of the author. Please send modifications to the author for
X * inclusion in updates to the program. Thanks.
X */
X
X/*
X * Mode definitions. These will be used by init(), and by the mode
X * program or shell script. As much as possible, the numeric mode
X * values should correspond to those used by the uPort screen driver
X * and by DOS. The values given for hercules and for printers are
X * arbitrary, but should not conflict with other "standard" assignments.
X */
X
X/* ENV_MODE means take the mode setting from an environment variable. */
X#define ENV_MODE 0
X
X/* CGA text modes */
X#define MONO_TEXT 0x02
X#define COLOR_TEXT 0x03
X
X/* CGA modes (for CGA or EGA) */
X#define CGA_COLOR_MODE 0x04
X#define CGA_HI_RES_MODE 0x06
X
X/* Monochrome text mode */
X#define MDA_TEXT 0x07
X
X/* Hercules mono graphics, page 0 and page 1 */
X/* Note: Modes 8 and 9 were used by the IBM PC Junior. I trust that */
X/* they will not be found on your machine. */
X#define HERC_P0_MODE 0x08
X#define HERC_P1_MODE 0x09
X
X/* EGA 640 x 350 color mode */
X#define EGA_COLOR_MODE 0x010
X
X/* Anything beyond MAXVIDEO is not a video board. Printers and other */
X/* hardcopy would fall in this category. */
X
X#define MAXVIDEO 0x0FF
X
X/* Non-video modes follow. */
X
X#define IBM_PRINTER 0x100
X#define LJ_PRINTER 0x101
X
X
XxX--EOF--XxX
echo restoring n_curves.c
sed 's/^X//' > n_curves.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) n_curves.c 5.1 89/02/20";
X#endif
X
X/*
X * Copyright (c) David T. Lewis 1988
X * All rights reserved.
X *
X * Permission is granted to use this for any personal noncommercial use.
X * You may not distribute source or executable code for profit, nor
X * may you distribute it with a commercial product without the written
X * consent of the author. Please send modifications to the author for
X * inclusion in updates to the program. Thanks.
X */
X
X/* Sat Aug 6 20:38:14 EDT 1988
X**
X** n_arc():
X**
X** Routine to draw an arc as a partial ellipse. This routine uses
X** parts of the ellipse() routine to generate the curve.
X** The arc is drawn around an ellipse located at (x,y) with axes a and b.
X** The arc begins at the angle angle1 and traverses counterclockwise to
X** angle2. "Counterclockwise" is in the sense of the normalized coordinate
X** system, with an inverted Y axis, so the arcs are actually drawn clockwise
X** on the display screen.
X** The values of angle1 and angle2 are given in radians, with 0 being to the
X** right of the center of the ellipse.
X**
X** n_ellipse():
X**
X** Routine to draw an ellipse in normalized 2-d coordinates. Uses a line
X** segment approximation to the ellipse. The trig is done with hard coded
X** tables of cos and sin values for speed. The number of vertices on the
X** ellipse varies according to the size of the ellipse. The eliminates
X** unnecessary calculations of endpoints for small images.
X** Another method for ellipe drawing would be to do a modified Bresenham
X** type algorithm, but this would be less adaptable for drawing partial arcs.
X**
X** NOTE: This is an ellipse routine, and not a circle, because the PC display
X** adapters do not generally have square pixels. A circle routine should be
X** done at a higher level, and should take the screen aspect ration into
X** account (see graphics->aspect_ratio in the graphics.h file).
X**
X** The basic idea is:
X**
X** Equation of an ellipse:
X**
X** x^2 / a^2 + y^2 / b^2 = 1
X**
X** Therefore the X and Y values are:
X**
X** X = a * cos(theta)
X** Y = b * sin(theta)
X**
X** For some angle theta.
X**
X** By stepping through values of theta, we can generate a list of
X** line segment endpoints on the ellipse. Then call n_movepen() and
X** n_draw() to display the ellipse.
X**
X** Note: The macros PTS_PER_QUADRANT and TRIG_SCALE are defined
X** in graphics.h.
X*/
X
X#include "config.h"
X#if MIX_C
X#else
X#include <math.h>
X#endif /* MIX_C */
X#include "bitmaps.h"
X#include "graphics.h"
X
X#ifndef M_PI
X#define M_PI 3.1415926536
X#endif /* M_PI */
X#ifndef M_PI_2
X#define M_PI_2 1.5707963268
X#endif /* M_PI_2 */
X
X#define XINDEX 0 /* For specifying array indices. */
X#define YINDEX 1
X
X/* The following two arrays are tables of values for cos and sin */
X/* for one quadrant of a circle, divided into PTS_PER_QUADRANT slices. */
X/* They are found in source file trig.c. */
X
Xextern long cos_table[PTS_PER_QUADRANT];
Xextern long sin_table[PTS_PER_QUADRANT];
Xextern long longsin(), longcos();
Xextern int n_movepen(), n_draw();
X
Xstatic void make_endpoints(x,y,a,b,endpoints,step)
Xint x,y,a,b,step;
Xint endpoints[4][PTS_PER_QUADRANT][2];
X{
X int idx; /* Loop index. */
X int value; /* Temporary storage of values */
X
X /* Set the values for points on the ellipse. While we're */
X /* at it, scale the values back down using TRIG_SCALE, and do */
X /* the x and y translation to the center point of the ellipse. */
X /* Calculations are done with long ints to preserve precision, */
X /* then cast back to short ints in the endpoints array. */
X /* Use the value of step to skip unnecessary points (for small */
X /* ellipes and arcs). */
X
X for(idx=step-1; idx<PTS_PER_QUADRANT; idx+= step) {
X value = (cos_table[idx] * (long)a) / TRIG_SCALE;
X endpoints[0][idx][XINDEX] = value + x;
X value = -value;
X endpoints[2][idx][XINDEX] = value + x;
X value = (sin_table[idx] * (long)a) / TRIG_SCALE;
X endpoints[3][idx][XINDEX] = value + x;
X value = -value;
X endpoints[1][idx][XINDEX] = value + x;
X value = (cos_table[idx] * (long)b) / TRIG_SCALE;
X endpoints[1][idx][YINDEX] = value + y;
X value = -value;
X endpoints[3][idx][YINDEX] = value + y;
X value = (sin_table[idx] * (long)b) / TRIG_SCALE;
X endpoints[0][idx][YINDEX] = value + y;
X value = -value;
X endpoints[2][idx][YINDEX] = value + y;
X }
X return;
X}
X
Xstatic int make_step(a,b)
Xint a,b;
X{
X int size;
X size = a + b; /* an indication of the "size" of the ellipse. */
X if (size <= 0) return(1); /* Check for integer overflow. */
X else if (size < 2000) return(16);
X else if (size < 8000) return(8);
X else if (size < 16000) return(4);
X else if (size < 32000) return(2);
X else return(1);
X}
X
Xint n_arc(x,y,a,b,angle1,angle2)
Xint x,y,a,b;
Xfloat angle1,angle2;
X{
X int endpoints[4][PTS_PER_QUADRANT][2];
X int x_1,y_1,x_2,y_2; /* The start and end points of the arc. */
X int quadrant; /* Quadrant of first point. */
X int endquadrant; /* Quadrant of second point. */
X int index; /* First index into endpoints array. */
X int endindex; /* Last index into endpoints array. */
X int istat = 0; /* Function call return status. */
X int step; /* Amount by which to step through array. */
X
X /* Size of a circle, in radians. */
X float cir_size = M_PI * 2;
X
X /* Don't feed huge numbers to the trig functions. */
X if (fabs(angle1) > cir_size)
X angle1 = fmod((double)angle1,(double)cir_size);
X if (fabs(angle2) > cir_size)
X angle2 = fmod((double)angle2,(double)cir_size);
X
X /* Make the angles positive. */
X while (angle1 < 0) angle1 += cir_size;
X while (angle2 < 0) angle2 += cir_size;
X
X /* Calculate a value for step, so we can use fewer endpoints */
X /* for small arcs. */
X step = make_step(a,b);
X
X#ifdef DEBUG
X printf("step is %d\n",step);
X#endif /* DEBUG */
X
X /* Calculate the end points. */
X
X#if NOFLOAT
X x_1 = x + (int)((longcos(angle1) * a) / TRIG_SCALE);
X y_1 = y + (int)((longsin(angle1) * b) / TRIG_SCALE);
X x_2 = x + (int)((longcos(angle2) * a) / TRIG_SCALE);
X y_2 = y + (int)((longsin(angle2) * b) / TRIG_SCALE);
X#else
X x_1 = x + (int)(a * cos((double)angle1));
X y_1 = y + (int)(b * sin((double)angle1));
X x_2 = x + (int)(a * cos((double)angle2));
X y_2 = y + (int)(b * sin((double)angle2));
X#endif /* NOFLOAT */
X
X /* Generate the array of arc endpoints. */
X make_endpoints(x,y,a,b,endpoints,step);
X
X /* Deduce the first and last element of interest in the */
X /* endpoint array. */
X
X /* First calculate the initial index value. */
X index = (int)(angle1 / M_PI_2 * (float)PTS_PER_QUADRANT);
X /* Now figure the quadrant. */
X quadrant = (index / PTS_PER_QUADRANT) % 4;
X /* Wrap around so we point at the array. */
X index = (index % PTS_PER_QUADRANT);
X index = index + step - (index % step) - 1;
X
X#ifdef DEBUG
X printf("In n_arc(), index is %d\n",index);
X#endif /* DEBUG */
X
X /* Calculate the final index value. */
X endindex = (int)(angle2 / M_PI_2 * (float)PTS_PER_QUADRANT);
X /* Now figure the quadrant. */
X endquadrant = (endindex / PTS_PER_QUADRANT) % 4;
X /* Wrap around so we point at the array. */
X endindex = (endindex % PTS_PER_QUADRANT);
X endindex = endindex + step - (endindex % step) - 1;
X
X#ifdef DEBUG
X printf("In n_arc(), endindex is %d\n",endindex);
X#endif /* DEBUG */
X
X /* Move pen to start point. */
X
X#ifdef DEBUG
X printf("Move pen to %d %d\n",x_1,y_1);
X#endif /* DEBUG */
X
X if(n_movepen(x_1,y_1)) istat = 1;
X
X /* Start drawing, beginning with the first point of interest. */
X /* Wrap around the array if needed. */
X
X while ((index != endindex) || (quadrant != endquadrant)) {
X
X#ifdef DEBUG
X printf("Draw to %d %d -- quadrant %d index %d\n",
X endpoints[quadrant][index][XINDEX],
X endpoints[quadrant][index][YINDEX],quadrant,index);
X#endif /* DEBUG */
X
X if(n_draw(endpoints[quadrant][index][XINDEX],
X endpoints[quadrant][index][YINDEX])) {
X istat = 1;
X /* This is just for cleaner error recovery: */
X n_movepen(endpoints[quadrant][index][XINDEX],
X endpoints[quadrant][index][YINDEX]);
X }
X /* Increment the indices. */
X if ((index+=step) >= PTS_PER_QUADRANT) {
X index = step - 1;
X if ((++quadrant) >= 4) {
X quadrant = 0;
X }
X }
X };
X
X /* Finish at last point of interest. */
X
X#ifdef DEBUG
X printf("Finish by drawing to %d %d\n",x_2,y_2);
X#endif /* DEBUG */
X
X if(n_draw(x_2,y_2)) {
X istat = 1;
X /* This is just for cleaner error recovery: */
X n_movepen(x_2,y_2);
X }
X return(istat);
X}
X
Xint n_ellipse(x,y,a,b)
Xint x,y,a,b;
X{
X /* The endpoints array will hold line segment (x,y) end points. */
X /* There are four quadrants, each with PTS_PER_QUADRANT points, */
X /* with two values (X and Y) each. */
X int endpoints[4][PTS_PER_QUADRANT][2];
X int pointindex, quadrant; /* Loop index. */
X int istat = 0; /* Function call return status. */
X int step; /* Amount by which to step through array. */
X
X /* Calculate a value for step, so we can use fewer endpoints */
X /* for small ellipses. */
X step = make_step(a,b);
X
X /* Build the array of endpoints. */
X make_endpoints(x,y,a,b,endpoints,step);
X
X /* Display the result, drawing all four quadrants. */
X
X /* Start the pen at the location of the last endpoint. This */
X /* is the point we want to end up on. */
X if(n_movepen(endpoints[3][PTS_PER_QUADRANT-1][XINDEX],
X endpoints[3][PTS_PER_QUADRANT-1][YINDEX]))
X istat = 1;
X
X for (quadrant=0; quadrant<=3; quadrant++) {
X
X for (pointindex = step -1; pointindex < PTS_PER_QUADRANT;
X pointindex += step) {
X if(n_draw(endpoints[quadrant][pointindex][XINDEX],
X endpoints[quadrant][pointindex][YINDEX])) {
X istat = 1;
X /* This is just for cleaner error recovery: */
X n_movepen(endpoints[quadrant][pointindex]
X [XINDEX],
X endpoints[quadrant][pointindex]
X [YINDEX]);
X }
X }
X }
X return(istat);
X}
X
XxX--EOF--XxX
echo restoring plot.c
sed 's/^X//' > plot.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) plot.c 5.1 89/02/20";
X#endif
X
X/*
X * Copyright (c) David T. Lewis 1988
X * All rights reserved.
X *
X * Permission is granted to use this for any personal noncommercial use.
X * You may not distribute source or executable code for profit, nor
X * may you distribute it with a commercial product without the written
X * consent of the author. Please send modifications to the author for
X * inclusion in updates to the program. Thanks.
X */
X
X#include "config.h"
X#include "gf_types.h"
X#include <stdio.h>
X#if MIX_C
X#else
X#include <math.h>
X#endif /* MIX_C */
X#include "modes.h"
X#include "bitmaps.h"
X#include "graphics.h"
X
X/* The following declarations copied from gl.h. */
Xextern int g_clear();
Xextern int g_init();
Xextern int g_finish();
Xextern long g_style();
Xextern int c_cellstr();
Xextern int n_movepen();
Xextern int n_line();
Xextern int n_draw();
Xextern int n_arc();
Xextern int n_ellipse();
Xextern int n_point();
X
Xextern struct GL_graphics graphics;
X
X/* These routines emulate the BSD plot(3) library.
X *
X * The arc() routine may vary slightly from the BSD version,
X * in that it calculates start and end angles with trig
X * functions, rather than with simple integer approximations
X * used in the BSD routine.
X *
X * plot: openpl, erase, label, line, circle, arc, move, cont,
X * point, linemod, space, closepl - graphics interface
X *
X * Coordinate transformations, using X0, X1, Y0, Y1 set in space():
X * X:
X * x' = x * (NRM_X_RANGE)/(X1-X0) - (X0*NRM_X_RANGE)/(X1-X0)
X * x' = (X0*NRM_X_RANGE + x*NRM_X_RANGE) / (X1-X0)
X *
X * xconst = X0*NRM_X_RANGE;
X * xdiv = X1-X0;
X * x' = (xconst+x*NRM_X_RANGE)/xdiv;
X *
X * Y:
X * y' = y * (-NRM_Y_RANGE)/(Y1-Y0) + (Y1*NRM_Y_RANGE)/(Y1-Y0)
X * y' = (Y1*NRM_Y_RANGE - y*NRM_Y_RANGE) / (Y1-Y0)
X *
X * yconst = Y1*NRM_Y_RANGE;
X * ydiv = Y1-Y0;
X * y' = (yconst-y*NRM_Y_RANGE)/ydiv;
X */
X
X/* X_TO_NORM(x) and Y_TO_NORM(y) are used to translate from the plot() */
X/* coordinate system, as defined by scale(), to the normalized 2-D */
X/* coordinate system of the screen. */
X
X#define X_TO_NORM(x) ((int)((xconst+x*NRM_X_RANGE)/xdiv))
X#define Y_TO_NORM(y) ((int)((yconst-y*NRM_Y_RANGE)/ydiv))
X
X/* X_SCALE_NORM() and Y_SCALE_NORM() are used for scaling magnitudes. */
X
X#define X_SCALE_NORM(x) (((x)*(NRM_X_RANGE))/(xdiv))
X#define Y_SCALE_NORM(y) (((y)*(NRM_Y_RANGE))/(ydiv))
X
Xstatic long xconst,xdiv,yconst,ydiv; /* Used in space() transforms. */
X
Xint openpl()
X{
X /* Try to get the mode from the environment. */
X /* If no environment variable, use a default. */
X if((g_init(ENV_MODE)) == 0) return(0);
X else {
X /* Put warning message to standard error, then */
X /* continue. */
X fprintf(stderr,"Use environment variable %s to control mode.\n",
X GL_ENV_MODE);
X fprintf(stderr,"Continuing with default mode %d\n",
X DEFAULT_MODE);
X sleep(2);
X return(g_init(DEFAULT_MODE));
X }
X}
X
Xint erase()
X{
X return(g_clear());
X}
X
Xint label(s)
Xchar s[];
X{
X return(c_cellstr(s));
X}
X
Xint line(x_1, y_1, x_2, y_2)
Xint x_1,y_1,x_2,y_2;
X{
X return(n_line(
X X_TO_NORM(x_1),Y_TO_NORM(y_1),X_TO_NORM(x_2),Y_TO_NORM(y_2)));
X}
X
Xint circle(x, y, r)
X{
X int x_axis=X_SCALE_NORM(r);
X int y_axis=Y_SCALE_NORM(r);
X return(n_ellipse(X_TO_NORM(x), Y_TO_NORM(y), x_axis, y_axis));
X}
X
Xint arc(x, y, x_0, y_0, x_1, y_1)
X{
X int x_axis, y_axis; /* Major and minor axes. */
X float angle1, angle2; /* Start and end angles. */
X int radius; /* Radius, as calculated from sqrt(x**2+y**2). */
X long dx_0 = x_0 - x;
X long dy_0 = y_0 - y;
X long dx_1 = x_1 - x;
X long dy_1 = y_1 - y;
X
X /* We will draw a section of elliptical arc with major and */
X /* minor axes such that it appears as a circle on the screen. */
X /* We know the center of the arc (x and y), and the ratio of */
X /* the major and minor axes (b/a equals graphics.aspect_ratio). */
X /* Given the start and end points of the arc, we need to solve */
X /* for the first and second angle, and then for major and minor */
X /* axes. */
X /* These values can be used to call the n_arc() routine. */
X
X /* WARNING: The value of angle2 is calculated directly as the */
X /* angle of the vector from (x,y) to (x_1,y_1). The original */
X /* versions of plot(3) from the BSD code apparently use */
X /* a simplistic approximation to this, which may lead to */
X /* different screen displays for arcs drawn with the BSD */
X /* code. The basic idea for the user, however, should be to */
X /* specify x_1 and y_1 such that they fall very close to the */
X /* intended angle. */
X
X angle1 = (float)(-atan2((double)dy_0,(double)dx_0));
X angle2 = (float)(-atan2((double)dy_1,(double)dx_1));
X
X radius = ((int)(sqrt(fabs((double)(dx_0*dx_0+dy_0*dy_0)))));
X x_axis = X_SCALE_NORM(radius);
X y_axis = Y_SCALE_NORM(radius);
X
X return(n_arc(X_TO_NORM(x),Y_TO_NORM(y),x_axis,y_axis,angle2,angle1));
X}
X
Xint move(x, y)
Xint x,y;
X{
X return(n_movepen(X_TO_NORM(x),Y_TO_NORM(y)));
X}
X
Xint cont(x, y)
Xint x,y;
X{
X return(n_draw(X_TO_NORM(x),Y_TO_NORM(y)));
X}
X
Xint point(x, y)
Xint x, y;
X{
X return(n_point(X_TO_NORM(x),Y_TO_NORM(y)));
X}
X
Xint linemod(s)
Xchar s[];
X{
X if (strncmp(s, "dotted", 6) == 0) {
X g_style(DOTTED);
X }
X else if (strncmp(s, "dotdashed", 9) == 0) {
X g_style(DOTDASHED);
X }
X else if (strncmp(s, "longdashed", 10) == 0) {
X g_style(LONGDASHED);
X }
X else if (strncmp(s, "shortdashed", 11) == 0) {
X g_style(SHORTDASHED);
X }
X else if (strncmp(s, "solid", 5) == 0) {
X g_style(SOLID);
X }
X else {
X g_style(SOLID);
X }
X return(0);
X}
X
Xint space(x_0, y_0, x_1, y_1)
X{
X /* Set constants for coordinate transformations. */
X /* Adjust x axis for aspect ratio so that output is square. */
X
X xconst = (long)(x_0) * NRM_X_RANGE;
X xdiv = (long)((float)(x_1-x_0) / graphics.aspect_ratio);
X yconst = y_1*NRM_Y_RANGE;
X ydiv = y_1-y_0;
X}
X
Xint closepl()
X{
X return(g_finish());
X}
X
XxX--EOF--XxX
echo restoring trig.c
sed 's/^X//' > trig.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) trig.c 5.1 89/02/20";
X#endif
X
X/*
X * Copyright (c) David T. Lewis 1988
X * All rights reserved.
X *
X * Permission is granted to use this for any personal noncommercial use.
X * You may not distribute source or executable code for profit, nor
X * may you distribute it with a commercial product without the written
X * consent of the author. Please send modifications to the author for
X * inclusion in updates to the program. Thanks.
X */
X
X/* Integer approximations to simple trig functions. Results are scaled */
X/* by a factor of TRIG_SCALE. */
X
X/* The macro TRIG_SCALE is defined in graphics.h so that other routines */
X/* can use it. F_TRIG_SCALE is the same value, but in floating point */
X/* format. The defines should look like this: */
X/* */
X/* #define TRIG_SCALE 32768 */
X/* #define F_TRIG_SCALE 32768.0 */
X/* */
X/* The macro PTS_PER_QUADRANT defines the size of the sin_table and */
X/* cos_table arrays. It is defined in graphics.h and should look */
X/* like this: */
X/* */
X/* #define PTS_PER_QUADRANT 64 */
X/* */
X
X#include "config.h"
X#if MIX_C
X#else
X#include <math.h>
X#endif /* MIX_C */
X#include "bitmaps.h"
X#include "graphics.h"
X
X#define L_PI 102944L /* Value of pi times TRIG_SCALE. */
X#define L_PI_2 51472L /* Value of pi/2 times TRIG_SCALE. */
X#define L_PI_4 25736L /* Value of pi/4 times TRIG_SCALE. */
X
X#define CIRCLE_SIZE 205887L /* Value of pi * 2 * TRIG_SCALE. */
X
X#define TABLESLICE 804L /* (L_PI_2 / PTS_PER_QUADRANT) */
X
X#define XINDEX 0 /* For specifying array indices. */
X#define YINDEX 1
X
X/* The following two arrays are tables of values for cos and sin */
X/* for one quadrant of a circle, divided into PTS_PER_QUADRANT slices. */
X
Xlong cos_table[PTS_PER_QUADRANT] = {
X 32758L, 32729L, 32679L, 32610L, 32522L, 32413L, 32286L, 32138L,
X 31972L, 31786L, 31581L, 31357L, 31114L, 30853L, 30572L, 30274L,
X 29957L, 29622L, 29269L, 28899L, 28511L, 28106L, 27684L, 27246L,
X 26791L, 26320L, 25833L, 25330L, 24812L, 24279L, 23732L, 23170L,
X 22595L, 22006L, 21403L, 20788L, 20160L, 19520L, 18868L, 18205L,
X 17531L, 16846L, 16151L, 15447L, 14733L, 14010L, 13279L, 12540L,
X 11793L, 11039L, 10279L, 9512L, 8740L, 7962L, 7180L, 6393L,
X 5602L, 4808L, 4011L, 3212L, 2411L, 1608L, 804L, 0L
X};
X
Xlong sin_table[PTS_PER_QUADRANT] = {
X 804L, 1608L, 2411L, 3212L, 4011L, 4808L, 5602L, 6393L,
X 7180L, 7962L, 8740L, 9512L, 10279L, 11039L, 11793L, 12540L,
X 13279L, 14010L, 14733L, 15447L, 16151L, 16846L, 17531L, 18205L,
X 18868L, 19520L, 20160L, 20788L, 21403L, 22006L, 22595L, 23170L,
X 23732L, 24279L, 24812L, 25330L, 25833L, 26320L, 26791L, 27246L,
X 27684L, 28106L, 28511L, 28899L, 29269L, 29622L, 29957L, 30274L,
X 30572L, 30853L, 31114L, 31357L, 31581L, 31786L, 31972L, 32138L,
X 32286L, 32413L, 32522L, 32610L, 32679L, 32729L, 32758L, 32768L
X};
X
X/* Estimate sin by interpolation. Return long integer value. */
X
Xlong longsin(theta)
Xfloat theta;
X{
X long longtheta;
X int quadrant;
X long value1, value2;
X long value;
X long intpart;
X long fractionpart;
X
X /* We have a floating point value for theta. Put theta */
X /* into a long integer for the rest of the processing. */
X /* Keep everything scaled by a factor of TRIG_SCALE. */
X
X longtheta = (long)(theta * F_TRIG_SCALE);
X
X /* Make angle positive. */
X
X while (longtheta < 0) longtheta += CIRCLE_SIZE;
X
X /* Figure quadrant while making it less than PI/2. */
X
X quadrant = 1;
X
X while (longtheta > L_PI_2) {
X longtheta -= L_PI_2;
X quadrant++;
X if (quadrant > 4) quadrant = 1;
X }
X
X /* If Quadrant 2 or 4 we need to use the reverse of the */
X /* interpolation table. */
X
X if (quadrant == 2 || quadrant == 4) longtheta = L_PI_2 - longtheta;
X
X /* Express angle in terms of number of table increments. */
X
X intpart = longtheta / TABLESLICE;
X
X fractionpart = longtheta % TABLESLICE;
X
X /* This looks like a kludge, but it isn't. When TABLESLICE is */
X /* set to TABLESLICE, we have the smallest error in the result. */
X /* This just rounds back down when we overshoot the table. */
X
X if (intpart >= PTS_PER_QUADRANT) {
X intpart = PTS_PER_QUADRANT - 1;
X fractionpart = TABLESLICE;
X }
X
X /* Interpolate. */
X
X if (intpart <= 0) {
X value1 = 0;
X value2 = sin_table[0];
X }
X else {
X value2 = sin_table[(int)(intpart--)];
X value1 = sin_table[(int)intpart];
X }
X
X value = value1 + (fractionpart * (value2 - value1)) / TABLESLICE;
X
X /* If Quadrant 3 or 4 the result should be negative. */
X
X if (quadrant == 3 || quadrant == 4) return(-value);
X else return(value);
X}
X
X
X/* Estimate cos by interpolation. Return long integer value. */
X
Xlong longcos(theta)
Xfloat theta;
X{
X long longtheta;
X int quadrant;
X long value1, value2;
X long value;
X long intpart;
X long fractionpart;
X
X /* We have a floating point value for theta. Put theta */
X /* into a long integer for the rest of the processing. */
X /* Keep everything scaled by a factor of TRIG_SCALE. */
X
X longtheta = (long)(theta * F_TRIG_SCALE);
X
X /* Make angle positive. */
X
X while (longtheta < 0) longtheta += CIRCLE_SIZE;
X
X /* Figure quadrant while making it less than PI/2. */
X
X quadrant = 1;
X
X while (longtheta > L_PI_2) {
X longtheta -= L_PI_2;
X quadrant++;
X if (quadrant > 4) quadrant = 1;
X }
X
X /* If Quadrant 2 or 4 we need to use the reverse of the */
X /* interpolation table. */
X
X if (quadrant == 2 || quadrant == 4) longtheta = L_PI_2 - longtheta;
X
X /* Express angle in terms of number of table increments. */
X
X intpart = longtheta / TABLESLICE;
X
X fractionpart = longtheta % TABLESLICE;
X
X /* This looks like a kludge, but it isn't. When TABLESLICE is */
X /* set to TABLESLICE, we have the smallest error in the result. */
X /* This just rounds back down when we overshoot the table. */
X
X if (intpart >= PTS_PER_QUADRANT) {
X intpart = PTS_PER_QUADRANT - 1;
X fractionpart = TABLESLICE;
X }
X
X /* Interpolate. */
X
X if (intpart <= 0) {
X value1 = 32768L;
X value2 = cos_table[0];
X }
X else {
X value2 = cos_table[(int)(intpart--)];
X value1 = cos_table[(int)intpart];
X }
X
X value = value1 + (fractionpart * (value2 - value1)) / TABLESLICE;
X
X /* If Quadrant 2 or 3 the result should be negative. */
X
X if (quadrant == 2 || quadrant == 3) return(-value);
X else return(value);
X}
X
X/* Test program:
Xmain() {
X float theta;
X
Xfloat sinval;
Xfloat lsinval;
Xfloat cosval;
Xfloat lcosval;
X
X for (theta = -8.3; theta < 100.0; theta += 0.1) {
X
X sinval = sin((double)theta);
X lsinval = longsin(theta) / F_TRIG_SCALE;
X cosval = cos((double)theta);
X lcosval = longcos(theta) / F_TRIG_SCALE;
X
X printf("SIN: angle %g %lg %g err %g\n",theta,sinval,
X lsinval,sinval-lsinval);
X printf("COS: angle %g %lg %g err %g\n",theta,cosval,
X lcosval,cosval-lcosval);
X }
X}
X*/
X
XxX--EOF--XxX