home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume24
/
gnuplot3
/
part04
< prev
next >
Wrap
Text File
|
1991-10-26
|
49KB
|
1,781 lines
Newsgroups: comp.sources.misc
From: gershon%gr@cs.utah.edu (Elber Gershon)
Subject: v24i026: gnuplot3 - interactive function plotting utility, Part04/26
Message-ID: <1991Oct26.222204.6282@sparky.imd.sterling.com>
X-Md4-Signature: c3149ff098bc8e28f256ddab05c10cd8
Date: Sat, 26 Oct 1991 22:22:04 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: gershon%gr@cs.utah.edu (Elber Gershon)
Posting-number: Volume 24, Issue 26
Archive-name: gnuplot3/part04
Environment: UNIX, MS-DOS, VMS
Supersedes: gnuplot2: Volume 11, Issue 65-79
#!/bin/sh
# this is Part.04 (part 4 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file gnuplot/bitmap.c continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 4; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping gnuplot/bitmap.c'
else
echo 'x - continuing file gnuplot/bitmap.c'
sed 's/^X//' << 'SHAR_EOF' >> 'gnuplot/bitmap.c' &&
*/
void
b_makebitmap(x, y, planes)
unsigned int x, y, planes;
{
X register unsigned j;
X unsigned rows;
X
X x = 8 * (unsigned int)(x/8.0+0.9); /* round up to multiple of 8 */
X y = 8 * (unsigned int)(y/8.0+0.9); /* round up to multiple of 8 */
X b_psize = y/8; /* size of each plane */
X rows = b_psize * planes; /* total number of rows of 8 pixels high */
X b_xsize = x; b_ysize = y;
X b_currx = b_curry = 0;
X b_planes = planes;
X b_value = 1;
X b_angle = 0;
X b_rastermode = 0;
X /* allocate row pointers */
X b_p = (bitmap *)alloc( rows * sizeof(pixels *), "bitmap row buffer");
X bzero(b_p, rows * sizeof(pixels *));
X for (j = 0; j < rows; j++) {
X /* allocate bitmap buffers */
X (*b_p)[j] = (pixels *)alloc(x * sizeof(pixels),(char *)NULL);
X if ((*b_p)[j] == (pixels *)NULL) {
X b_freebitmap(); /* free what we have already allocated */
X int_error("out of memory for bitmap buffer", NO_CARET);
X }
X bzero((*b_p)[j], x * sizeof(pixels));
X }
}
X
/*
** free the allocated bitmap
*/
void
b_freebitmap()
{
X int j;
X unsigned rows;
X
X rows = b_psize * b_planes; /* total number of rows of 8 pixels high */
X for (j = 0; j < rows; j++)
X {
X (void) free((char *)(*b_p)[j]);
X }
X (void) free((char *)b_p);
X b_p = (bitmap *)(NULL);
}
X
/*
** set pixel at (x,y) with color b_value and dotted mask b_linemask.
*/
void
b_setmaskpixel(x,y,value)
unsigned int x,y,value;
{
X /* dotted line generator */
X if ((b_linemask>>b_maskcount)&(unsigned int)(1)) {
X b_setpixel(x,y,value);
X }
X b_maskcount= (b_maskcount+1) % 16;
X b_lastx= x; /* last pixel set with mask */
X b_lasty= y;
}
X
/*
** draw a line from (x1,y1) to (x2,y2)
** with color b_value and dotted mask b_linemask.
*/
void
b_line(x1,y1,x2,y2)
unsigned int x1,y1,x2,y2;
{
int runcount;
int dx,dy;
int xinc,yinc;
unsigned int xplot,yplot;
X
X runcount=0;
X dx = abs((int)(x1)-(int)(x2));
X if (x2>x1) xinc= 1;
X if (x2==x1) xinc= 0;
X if (x2<x1) xinc= -1;
X dy = abs((int)(y1)-(int)(y2));
X if (y2>y1) yinc= 1;
X if (y2==y1) yinc= 0;
X if (y2<y1) yinc= -1;
X xplot=x1;
X yplot=y1;
X if (dx>dy) {
X /* iterate x */
X if ( (b_linemask==0xffff) ||
X ((xplot!=b_lastx) && (yplot!=b_lasty)) )
X b_setmaskpixel(xplot,yplot,b_value);
X while (xplot!=x2) {
X xplot+=xinc;
X runcount+=dy;
X if (runcount>=(dx-runcount)) {
X yplot+=yinc;
X runcount-=dx;
X }
X b_setmaskpixel(xplot,yplot,b_value);
X }
X } else {
X /* iterate y */
X if ( (b_linemask==0xffff) ||
X ((xplot!=b_lastx) && (yplot!=b_lasty)) )
X b_setmaskpixel(xplot,yplot,b_value);
X while (yplot!=y2) {
X yplot+=yinc;
X runcount+=dx;
X if (runcount>=(dy-runcount)) {
X xplot+=xinc;
X runcount-=dy;
X }
X b_setmaskpixel(xplot,yplot,b_value);
X }
X }
}
X
/*
** set character size
*/
void
b_charsize(size)
unsigned int size;
{
X int j;
X switch(size) {
X case FNT5X9:
X b_hchar = FNT5X9_HCHAR;
X b_hbits = FNT5X9_HBITS;
X b_vchar = FNT5X9_VCHAR;
X b_vbits = FNT5X9_VBITS;
X for (j = 0; j < FNT_CHARS; j++ )
X b_font[j] = &fnt5x9[j][0];
X break;
X case FNT9X17:
X b_hchar = FNT9X17_HCHAR;
X b_hbits = FNT9X17_HBITS;
X b_vchar = FNT9X17_VCHAR;
X b_vbits = FNT9X17_VBITS;
X for (j = 0; j < FNT_CHARS; j++ )
X b_font[j] = &fnt9x17[j][0];
X break;
X case FNT13X25:
X b_hchar = FNT13X25_HCHAR;
X b_hbits = FNT13X25_HBITS;
X b_vchar = FNT13X25_VCHAR;
X b_vbits = FNT13X25_VBITS;
X for (j = 0; j < FNT_CHARS; j++ )
X b_font[j] = &fnt13x25[j][0];
X break;
X default:
X int_error("Unknown character size",NO_CARET);
X }
}
X
X
/*
** put characater c at (x,y) rotated by angle with color b_value.
*/
void
b_putc(x,y,c,angle)
unsigned int x,y;
char c;
unsigned int angle;
{
X unsigned int i, j, k;
X char_row fc;
X
X j = c - ' ';
X for ( i = 0; i < b_vbits; i++ ) {
X fc = *( b_font[j] + i );
X if ( c == '_' ) { /* treat underline specially */
X if ( fc ) { /* this this the underline row ? *?
X /* draw the under line for the full h_char width */
X for ( k = ( b_hbits - b_hchar )/2;
X k < ( b_hbits + b_hchar )/2; k++ ) {
X switch(angle) {
X case 0 : b_setpixel(x+k+1,y+i,b_value);
X break;
X case 1 : b_setpixel(x-i,y+k+1,b_value);
X break;
X }
X }
X }
X }
X else {
X /* draw character */
X for ( k = 0; k < b_hbits; k++ ) {
X if ( ( fc >> k ) & 1 ) {
X switch(angle) {
X case 0 : b_setpixel(x+k+1,y+i,b_value);
X break;
X case 1 : b_setpixel(x-i,y+k+1,b_value);
X break;
X }
X }
X }
X }
X }
}
X
X
/*
** set b_linemask to b_pattern[linetype]
*/
int
b_setlinetype(linetype)
int linetype;
{
X if (linetype>=7)
X linetype %= 7;
X b_linemask = b_pattern[linetype+2];
X b_maskcount=0;
}
X
/*
** set b_value to value
*/
void
b_setvalue(value)
unsigned int value;
{
X b_value = value;
}
X
/*
** move to (x,y)
*/
int
b_move(x, y)
unsigned int x, y;
{
X b_currx = x;
X b_curry = y;
}
X
/*
** draw to (x,y) with color b_value
*/
int
b_vector(x, y)
unsigned int x, y;
{
X b_line(b_currx, b_curry, x, y);
X b_currx = x;
X b_curry = y;
}
X
X
/*
** put text str at (x,y) with color b_value and rotation b_angle
*/
int
b_put_text(x,y,str)
unsigned int x, y;
char *str;
{
X if (b_angle == 1)
X x += b_vchar/2;
X else
X y -= b_vchar/2;
X switch (b_angle) {
X case 0:
X for (; *str; ++str, x += b_hchar)
X b_putc (x, y, *str, b_angle);
X break;
X case 1:
X for (; *str; ++str, y += b_hchar)
X b_putc (x, y, *str, b_angle);
X break;
X }
}
X
X
int
b_text_angle(ang)
int ang;
{
X b_angle=(unsigned int)ang;
X return TRUE;
}
SHAR_EOF
echo 'File gnuplot/bitmap.c is complete' &&
chmod 0666 gnuplot/bitmap.c ||
echo 'restore of gnuplot/bitmap.c failed'
Wc_c="`wc -c < 'gnuplot/bitmap.c'`"
test 51656 -eq "$Wc_c" ||
echo 'gnuplot/bitmap.c: original size 51656, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= gnuplot/bitmap.h ==============
if test -f 'gnuplot/bitmap.h' -a X"$1" != X"-c"; then
echo 'x - skipping gnuplot/bitmap.h (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting gnuplot/bitmap.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gnuplot/bitmap.h' &&
/* bitmap.h */
X
/* allow up to 16 bit width for character array */
typedef unsigned int char_row;
typedef char_row * char_box;
X
#define FNT_CHARS 96 /* Number of characters in the font set */
X
#define FNT5X9 0
#define FNT5X9_VCHAR 11 /* vertical spacing between characters */
#define FNT5X9_VBITS 9 /* actual number of rows of bits per char */
#define FNT5X9_HCHAR 7 /* horizontal spacing between characters */
#define FNT5X9_HBITS 5 /* actual number of bits per row per char */
extern char_row fnt5x9[FNT_CHARS][FNT5X9_VBITS];
X
#define FNT9X17 1
#define FNT9X17_VCHAR 21 /* vertical spacing between characters */
#define FNT9X17_VBITS 17 /* actual number of rows of bits per char */
#define FNT9X17_HCHAR 13 /* horizontal spacing between characters */
#define FNT9X17_HBITS 9 /* actual number of bits per row per char */
extern char_row fnt9x17[FNT_CHARS][FNT9X17_VBITS];
X
#define FNT13X25 2
#define FNT13X25_VCHAR 31 /* vertical spacing between characters */
#define FNT13X25_VBITS 25 /* actual number of rows of bits per char */
#define FNT13X25_HCHAR 19 /* horizontal spacing between characters */
#define FNT13X25_HBITS 13 /* actual number of bits per row per char */
extern char_row fnt13x25[FNT_CHARS][FNT13X25_VBITS];
X
X
typedef unsigned char pixels; /* the type of one set of 8 pixels in bitmap */
typedef pixels *bitmap[]; /* the bitmap */
X
extern bitmap *b_p; /* global pointer to bitmap */
extern unsigned int b_currx, b_curry; /* the current coordinates */
extern unsigned int b_xsize, b_ysize; /* the size of the bitmap */
extern unsigned int b_planes; /* number of color planes */
extern unsigned int b_psize; /* size of each plane */
extern unsigned int b_rastermode; /* raster mode rotates -90deg */
extern unsigned int b_linemask; /* 16 bit mask for dotted lines */
extern unsigned int b_value; /* colour of lines */
extern unsigned int b_hchar; /* width of characters */
extern unsigned int b_hbits; /* actual bits in char horizontally */
extern unsigned int b_vchar; /* height of characters */
extern unsigned int b_vbits; /* actual bits in char vertically */
extern unsigned int b_angle; /* rotation of text */
extern char_box b_font[FNT_CHARS]; /* the current font */
extern unsigned int b_pattern[];
extern int b_maskcount;
extern unsigned int b_lastx, b_lasty; /* last pixel set - used by b_line */
X
X
extern void b_makebitmap();
extern void b_freebitmap();
extern void b_setpixel();
extern unsigned int b_getpixel();
extern void b_line();
extern void b_setmaskpixel();
extern void b_putc();
extern void b_charsize();
extern void b_setvalue();
X
extern int b_setlinetype();
extern int b_move();
extern int b_vector();
extern int b_put_text();
extern int b_text_angle();
X
SHAR_EOF
chmod 0666 gnuplot/bitmap.h ||
echo 'restore of gnuplot/bitmap.h failed'
Wc_c="`wc -c < 'gnuplot/bitmap.h'`"
test 2726 -eq "$Wc_c" ||
echo 'gnuplot/bitmap.h: original size 2726, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= gnuplot/buildvms.com ==============
if test -f 'gnuplot/buildvms.com' -a X"$1" != X"-c"; then
echo 'x - skipping gnuplot/buildvms.com (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting gnuplot/buildvms.com (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gnuplot/buildvms.com' &&
$ ! buildvms.com (Command file to compile/link gnuplot and doc2hlp)
$ CFLAGS = "/NOOP/define=(NOGAMMA,MEMSET)"
$ !TERMFLAGS = "/define=()"
$ TERMFLAGS = ""
$ set verify
$ cc 'CFLAGS' bitmap.c
$ cc 'CFLAGS' command.c
$ cc 'CFLAGS' contour.c
$ cc 'CFLAGS' eval.c
$ cc 'CFLAGS' graphics.c
$ cc 'CFLAGS' graph3d.c
$ cc 'CFLAGS' internal.c
$ cc 'CFLAGS' misc.c
$ cc 'CFLAGS' parse.c
$ cc 'CFLAGS' plot.c
$ cc 'CFLAGS' scanner.c
$ cc 'CFLAGS' setshow.c
$ cc 'CFLAGS' standard.c
$ cc 'CFLAGS' 'TERMFLAGS' term.c
$ cc 'CFLAGS' util.c
$ cc 'CFLAGS' version.c
$ link /exe=gnuplot -
X bitmap.obj,command.obj,contour.obj,eval.obj,graphics.obj,graph3d.obj, -
X internal.obj,misc.obj,parse.obj,plot.obj,scanner.obj,setshow.obj, -
X standard.obj,term.obj,util.obj,version.obj ,linkopt.vms/opt
$ cc [.docs]doc2hlp.c
$ link doc2hlp,linkopt.vms/opt
$ @[.docs]doc2hlp.com
$ library/create/help gnuplot.hlb gnuplot.hlp
$ set noverify
SHAR_EOF
chmod 0644 gnuplot/buildvms.com ||
echo 'restore of gnuplot/buildvms.com failed'
Wc_c="`wc -c < 'gnuplot/buildvms.com'`"
test 918 -eq "$Wc_c" ||
echo 'gnuplot/buildvms.com: original size 918, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= gnuplot/misc.c ==============
if test -f 'gnuplot/misc.c' -a X"$1" != X"-c"; then
echo 'x - skipping gnuplot/misc.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting gnuplot/misc.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gnuplot/misc.c' &&
/* GNUPLOT - misc.c */
/*
X * Copyright (C) 1986, 1987, 1990, 1991 Thomas Williams, Colin Kelley
X *
X * Permission to use, copy, and distribute this software and its
X * documentation for any purpose with or without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and
X * that both that copyright notice and this permission notice appear
X * in supporting documentation.
X *
X * Permission to modify the software is granted, but not the right to
X * distribute the modified code. Modifications are to be distributed
X * as patches to released version.
X *
X * This software is provided "as is" without express or implied warranty.
X *
X *
X * AUTHORS
X *
X * Original Software:
X * Thomas Williams, Colin Kelley.
X *
X * Gnuplot 2.0 additions:
X * Russell Lang, Dave Kotz, John Campbell.
X *
X * Gnuplot 3.0 additions:
X * Gershon Elber and many others.
X *
X * Send your comments or suggestions to
X * pixar!info-gnuplot@sun.com.
X * This is a mailing list; to join it send a note to
X * pixar!info-gnuplot-request@sun.com.
X * Send bug reports to
X * pixar!bug-gnuplot@sun.com.
X */
X
#include <stdio.h>
#include <math.h>
#include "plot.h"
#include "setshow.h"
#include "help.h"
#ifdef __TURBOC__
#include <graphics.h>
#endif
X
#ifndef _IBMR2
extern char *malloc();
extern char *realloc();
#endif
X
extern int c_token;
extern char replot_line[];
extern struct at_type at;
extern struct ft_entry ft[];
extern struct udft_entry *first_udf;
extern struct udvt_entry *first_udv;
X
extern struct at_type *temp_at();
X
extern BOOLEAN interactive;
extern char *infile_name;
extern int inline_num;
X
/* State information for load_file(), to recover from errors
X * and properly handle recursive load_file calls
X */
typedef struct lf_state_struct LFS;
struct lf_state_struct {
X FILE *fp; /* file pointer for load file */
X char *name; /* name of file */
X BOOLEAN interactive; /* value of interactive flag on entry */
X int inline_num; /* inline_num on entry */
X LFS *prev; /* defines a stack */
} *lf_head = NULL; /* NULL if not in load_file */
X
static BOOLEAN lf_pop();
static void lf_push();
X
/*
X * instead of <strings.h>
X */
extern int strcmp();
X
/*
X * Turbo C realloc does not do the right thing. Here is what it should do.
X */
#ifdef __TURBOC__
char *realloc(p, new_size)
X void *p;
X size_t new_size;
{
X void *new_p = alloc(new_size, "TC realloc");
X
X /* Note p may have less than new_size bytes but in this unprotected
X * environment this will work.
X */
X memcpy(new_p, p, new_size);
X free(p);
X return new_p;
}
#endif /* __TURBOC__ */
X
/*
X * cp_alloc() allocates a curve_points structure that can hold 'num'
X * points.
X */
struct curve_points *
cp_alloc(num)
X int num;
{
X struct curve_points *cp;
X cp = (struct curve_points *) alloc(sizeof(struct curve_points), "curve");
X cp->p_max = (num >= 0 ? num : 0);
X if (num > 0) {
X cp->points = (struct coordinate *)
X alloc(num * sizeof(struct coordinate), "curve points");
X } else
X cp->points = (struct coordinate *) NULL;
X cp->next_cp = NULL;
X cp->title = NULL;
X return(cp);
}
X
X
/*
X * cp_extend() reallocates a curve_points structure to hold "num"
X * points. This will either expand or shrink the storage.
X */
cp_extend(cp, num)
X struct curve_points *cp;
X int num;
{
X struct coordinate *new;
X
#ifdef PC
X /* Make sure we do not allocate more than 64k (8088 architecture...)
X * in msdos since we can not address more. Leave some bytes for malloc
X * maintainance.
X */
X if (num > 65500L / sizeof(struct coordinate))
X int_error("Can not allocate more than 64k in msdos", NO_CARET);
#endif /* PC */
X
X if (num == cp->p_max) return;
X
X if (num > 0) {
X if (cp->points == NULL) {
X cp->points = (struct coordinate *)
X alloc(num * sizeof(struct coordinate), "curve points");
X } else {
X new = (struct coordinate *)
X realloc(cp->points, num * sizeof(struct coordinate));
X if (new == (struct coordinate *) NULL) {
X int_error("No memory available for expanding curve points",
X NO_CARET);
X /* NOTREACHED */
X }
X cp->points = new;
X }
X cp->p_max = num;
X } else {
X if (cp->points != (struct coordinate *) NULL)
X free(cp->points);
X cp->points = (struct coordinate *) NULL;
X cp->p_max = 0;
X }
}
X
/*
X * cp_free() releases any memory which was previously malloc()'d to hold
X * curve points (and recursively down the linked list).
X */
cp_free(cp)
struct curve_points *cp;
{
X if (cp) {
X cp_free(cp->next_cp);
X if (cp->title)
X free((char *)cp->title);
X if (cp->points)
X free((char *)cp->points);
X free((char *)cp);
X }
}
X
/*
X * iso_alloc() allocates a iso_curve structure that can hold 'num'
X * points.
X */
struct iso_curve *
iso_alloc(num)
X int num;
{
X struct iso_curve *ip;
X ip = (struct iso_curve *) alloc(sizeof(struct iso_curve), "iso curve");
X ip->p_max = (num >= 0 ? num : 0);
X if (num > 0) {
X ip->points = (struct coordinate *)
X alloc(num * sizeof(struct coordinate), "iso curve points");
X } else
X ip->points = (struct coordinate *) NULL;
X ip->next = NULL;
X return(ip);
}
X
/*
X * iso_extend() reallocates a iso_curve structure to hold "num"
X * points. This will either expand or shrink the storage.
X */
iso_extend(ip, num)
X struct iso_curve *ip;
X int num;
{
X struct coordinate *new;
X
X if (num == ip->p_max) return;
X
#ifdef PC
X /* Make sure we do not allocate more than 64k (8088 architecture...)
X * in msdos since we can not address more. Leave some bytes for malloc
X * maintainance.
X */
X if (num > 65500L / sizeof(struct coordinate))
X int_error("Can not allocate more than 64k in msdos", NO_CARET);
#endif /* PC */
X
X if (num > 0) {
X if (ip->points == NULL) {
X ip->points = (struct coordinate *)
X alloc(num * sizeof(struct coordinate), "iso curve points");
X } else {
X new = (struct coordinate *)
X realloc(ip->points, num * sizeof(struct coordinate));
X if (new == (struct coordinate *) NULL) {
X int_error("No memory available for expanding curve points",
X NO_CARET);
X /* NOTREACHED */
X }
X ip->points = new;
X }
X ip->p_max = num;
X } else {
X if (ip->points != (struct coordinate *) NULL)
X free(ip->points);
X ip->points = (struct coordinate *) NULL;
X ip->p_max = 0;
X }
}
X
/*
X * iso_free() releases any memory which was previously malloc()'d to hold
X * iso curve points.
X */
iso_free(ip)
struct iso_curve *ip;
{
X if (ip) {
X if (ip->points)
X free((char *)ip->points);
X free((char *)ip);
X }
}
X
/*
X * sp_alloc() allocates a surface_points structure that can hold 'num_iso'
X * iso-curves, each of which 'num_samp' samples.
X * if, however num_iso or num_samp is zero no iso curves are allocated.
X */
struct surface_points *
sp_alloc(num_samp,num_iso)
X int num_samp,num_iso;
{
X struct surface_points *sp;
X
X sp = (struct surface_points *) alloc(sizeof(struct surface_points), "surface");
X sp->next_sp = NULL;
X sp->title = NULL;
X sp->contours = NULL;
X sp->iso_crvs = NULL;
X sp->num_iso_read = 0;
X
X if (num_iso > 0 && num_samp > 0) {
X int i;
X struct iso_curve *icrv;
X
X for (i = 0; i < num_iso; i++) {
X icrv = iso_alloc(num_samp);
X icrv->next = sp->iso_crvs;
X sp->iso_crvs = icrv;
X }
X } else
X sp->iso_crvs = (struct iso_curve *) NULL;
X
X return(sp);
}
X
/*
X * sp_replace() updates a surface_points structure so it can hold 'num_iso'
X * iso-curves, each of which 'num_samp' samples.
X * if, however num_iso or num_samp is zero no iso curves are allocated.
X */
sp_replace(sp,num_samp,num_iso)
X struct surface_points *sp;
X int num_samp,num_iso;
{
X int i;
X struct iso_curve *icrv, *icrvs = sp->iso_crvs;
X
X while ( icrvs ) {
X icrv = icrvs;
X icrvs = icrvs->next;
X iso_free( icrv );
X }
X sp->iso_crvs = NULL;
X
X if (num_iso > 0 && num_samp > 0) {
X for (i = 0; i < num_iso; i++) {
X icrv = iso_alloc(num_samp);
X icrv->next = sp->iso_crvs;
X sp->iso_crvs = icrv;
X }
X } else
X sp->iso_crvs = (struct iso_curve *) NULL;
}
X
/*
X * sp_free() releases any memory which was previously malloc()'d to hold
X * surface points.
X */
sp_free(sp)
struct surface_points *sp;
{
X if (sp) {
X sp_free(sp->next_sp);
X if (sp->title)
X free((char *)sp->title);
X if (sp->contours) {
X struct gnuplot_contours *cntr, *cntrs = sp->contours;
X
X while (cntrs) {
X cntr = cntrs;
X cntrs = cntrs->next;
X free(cntr->coords);
X free(cntr);
X }
X }
X if (sp->iso_crvs) {
X struct iso_curve *icrv, *icrvs = sp->iso_crvs;
X
X while (icrvs) {
X icrv = icrvs;
X icrvs = icrvs->next;
X iso_free(icrv);
X }
X }
X free((char *)sp);
X }
}
X
X
X
save_functions(fp)
FILE *fp;
{
register struct udft_entry *udf = first_udf;
X
X if (fp) {
X while (udf) {
X if (udf->definition)
X fprintf(fp,"%s\n",udf->definition);
X udf = udf->next_udf;
X }
X (void) fclose(fp);
X } else
X os_error("Cannot open save file",c_token);
}
X
X
save_variables(fp)
FILE *fp;
{
register struct udvt_entry *udv = first_udv->next_udv; /* skip pi */
X
X if (fp) {
X while (udv) {
X if (!udv->udv_undef) {
X fprintf(fp,"%s = ",udv->udv_name);
X disp_value(fp,&(udv->udv_value));
X (void) putc('\n',fp);
X }
X udv = udv->next_udv;
X }
X (void) fclose(fp);
X } else
X os_error("Cannot open save file",c_token);
}
X
X
save_all(fp)
FILE *fp;
{
register struct udft_entry *udf = first_udf;
register struct udvt_entry *udv = first_udv->next_udv; /* skip pi */
X
X if (fp) {
X save_set_all(fp);
X while (udf) {
X if (udf->definition)
X fprintf(fp,"%s\n",udf->definition);
X udf = udf->next_udf;
X }
X while (udv) {
X if (!udv->udv_undef) {
X fprintf(fp,"%s = ",udv->udv_name);
X disp_value(fp,&(udv->udv_value));
X (void) putc('\n',fp);
X }
X udv = udv->next_udv;
X }
X fprintf(fp,"%s\n",replot_line);
X (void) fclose(fp);
X } else
X os_error("Cannot open save file",c_token);
}
X
X
save_set(fp)
FILE *fp;
{
X if (fp) {
X save_set_all(fp);
X (void) fclose(fp);
X } else
X os_error("Cannot open save file",c_token);
}
X
X
save_set_all(fp)
FILE *fp;
{
struct text_label *this_label;
struct arrow_def *this_arrow;
X fprintf(fp,"set terminal %s %s\n", term_tbl[term].name, term_options);
X fprintf(fp,"set output %s\n",strcmp(outstr,"STDOUT")? outstr : "" );
X fprintf(fp,"set %sclip points\n", (clip_points)? "" : "no");
X fprintf(fp,"set %sclip one\n", (clip_lines1)? "" : "no");
X fprintf(fp,"set %sclip two\n", (clip_lines2)? "" : "no");
X fprintf(fp,"set %sborder\n",draw_border ? "" : "no");
X fprintf(fp,"set dummy %s,%s\n",dummy_var[0], dummy_var[1]);
X fprintf(fp,"set format x \"%s\"\n", xformat);
X fprintf(fp,"set format y \"%s\"\n", yformat);
X fprintf(fp,"set format z \"%s\"\n", zformat);
X fprintf(fp,"set %sgrid\n", (grid)? "" : "no");
X switch (key) {
X case -1 :
X fprintf(fp,"set key\n");
X break;
X case 0 :
X fprintf(fp,"set nokey\n");
X break;
X case 1 :
X fprintf(fp,"set key %g,%g,%g\n",key_x,key_y,key_z);
X break;
X }
X fprintf(fp,"set nolabel\n");
X for (this_label = first_label; this_label != NULL;
X this_label = this_label->next) {
X fprintf(fp,"set label %d \"%s\" at %g,%g,%g ",
X this_label->tag,
X this_label->text, this_label->x,
X this_label->y,
X this_label->z);
X switch(this_label->pos) {
X case LEFT :
X fprintf(fp,"left");
X break;
X case CENTRE :
X fprintf(fp,"centre");
X break;
X case RIGHT :
X fprintf(fp,"right");
X break;
X }
X fputc('\n',fp);
X }
X fprintf(fp,"set noarrow\n");
X for (this_arrow = first_arrow; this_arrow != NULL;
X this_arrow = this_arrow->next) {
X fprintf(fp,"set arrow %d from %g,%g,%g to %g,%g,%g%s\n",
X this_arrow->tag,
X this_arrow->sx, this_arrow->sy, this_arrow->sz,
X this_arrow->ex, this_arrow->ey, this_arrow->ez,
X this_arrow->head ? "" : " nohead");
X }
X fprintf(fp,"set nologscale\n");
X if (log_x||log_y)
X fprintf(fp,"set logscale %c%c\n",
X log_x ? 'x' : ' ', log_y ? 'y' : ' ');
X if (log_z) fprintf(fp,"set logscale z\n");
X fprintf(fp,"set offsets %g, %g, %g, %g\n",loff,roff,toff,boff);
X fprintf(fp,"set %spolar\n", (polar)? "" : "no");
X fprintf(fp,"set angles %s\n", (angles_format == ANGLES_RADIANS)?
X "radians" : "degrees");
X fprintf(fp,"set %sparametric\n", (parametric)? "" : "no");
X fprintf(fp,"set view %g, %g, %g, %g\n",
X surface_rot_x, surface_rot_z, surface_scale, surface_zscale);
X fprintf(fp,"set samples %d\n",samples);
X fprintf(fp,"set isosamples %d\n",iso_samples);
X fprintf(fp,"set %ssurface\n",(draw_surface) ? "" : "no");
X fprintf(fp,"set %scontour",(draw_contour) ? "" : "no");
X switch (draw_contour) {
X case CONTOUR_NONE: fprintf(fp, "\n"); break;
X case CONTOUR_BASE: fprintf(fp, " base\n"); break;
X case CONTOUR_SRF: fprintf(fp, " surface\n"); break;
X case CONTOUR_BOTH: fprintf(fp, " both\n"); break;
X }
X fprintf(fp,"set cntrparam order %d\n", contour_order);
X fprintf(fp,"set cntrparam ");
X switch (contour_kind) {
X case CONTOUR_KIND_LINEAR: fprintf(fp, "linear\n"); break;
X case CONTOUR_KIND_CUBIC_SPL: fprintf(fp, "cubicspline\n"); break;
X case CONTOUR_KIND_BSPLINE: fprintf(fp, "bspline\n"); break;
X }
X fprintf(fp,"set cntrparam points %d\n", contour_pts);
X fprintf(fp,"set size %g,%g\n",xsize,ysize);
X fprintf(fp,"set data style ");
X switch (data_style) {
X case LINES: fprintf(fp,"lines\n"); break;
X case POINTS: fprintf(fp,"points\n"); break;
X case IMPULSES: fprintf(fp,"impulses\n"); break;
X case LINESPOINTS: fprintf(fp,"linespoints\n"); break;
X case DOTS: fprintf(fp,"dots\n"); break;
X case ERRORBARS: fprintf(fp,"errorbars\n"); break;
X }
X fprintf(fp,"set function style ");
X switch (func_style) {
X case LINES: fprintf(fp,"lines\n"); break;
X case POINTS: fprintf(fp,"points\n"); break;
X case IMPULSES: fprintf(fp,"impulses\n"); break;
X case LINESPOINTS: fprintf(fp,"linespoints\n"); break;
X case DOTS: fprintf(fp,"dots\n"); break;
X case ERRORBARS: fprintf(fp,"errorbars\n"); break;
X }
X fprintf(fp,"set tics %s\n", (tic_in)? "in" : "out");
X fprintf(fp,"set ticslevel %g\n", ticslevel);
X save_tics(fp, xtics, 'x', &xticdef);
X save_tics(fp, ytics, 'y', &yticdef);
X save_tics(fp, ztics, 'z', &zticdef);
X fprintf(fp,"set title \"%s\" %d,%d\n",title,title_xoffset,title_yoffset);
X if (timedate)
X fprintf(fp,"set time %d,%d\n",time_xoffset,time_yoffset);
X else
X fprintf(fp,"set notime\n");
X fprintf(fp,"set rrange [%g : %g]\n",rmin,rmax);
X fprintf(fp,"set trange [%g : %g]\n",tmin,tmax);
X fprintf(fp,"set xlabel \"%s\" %d,%d\n",xlabel,xlabel_xoffset,xlabel_yoffset);
X fprintf(fp,"set xrange [%g : %g]\n",xmin,xmax);
X fprintf(fp,"set ylabel \"%s\" %d,%d\n",ylabel,ylabel_xoffset,ylabel_yoffset);
X fprintf(fp,"set yrange [%g : %g]\n",ymin,ymax);
X fprintf(fp,"set zlabel \"%s\" %d,%d\n",zlabel,zlabel_xoffset,zlabel_yoffset);
X fprintf(fp,"set zrange [%g : %g]\n",zmin,zmax);
X fprintf(fp,"set %s %c\n",
X autoscale_r ? "autoscale" : "noautoscale", 'r');
X fprintf(fp,"set %s %c\n",
X autoscale_t ? "autoscale" : "noautoscale", 't');
X fprintf(fp,"set %s %c%c\n",
X (autoscale_y||autoscale_x) ? "autoscale" : "noautoscale",
X autoscale_x ? 'x' : ' ', autoscale_y ? 'y' : ' ');
X fprintf(fp,"set %s %c\n",
X autoscale_z ? "autoscale" : "noautoscale", 'z');
X fprintf(fp,"set zero %g\n",zero);
}
X
save_tics(fp, onoff, axis, tdef)
X FILE *fp;
X BOOLEAN onoff;
X char axis;
X struct ticdef *tdef;
{
X if (onoff) {
X fprintf(fp,"set %ctics", axis);
X switch(tdef->type) {
X case TIC_COMPUTED: {
X break;
X }
X case TIC_SERIES: {
X if (tdef->def.series.end >= VERYLARGE)
X fprintf(fp, " %g,%g", tdef->def.series.start,
X tdef->def.series.incr);
X else
X fprintf(fp, " %g,%g,%g", tdef->def.series.start,
X tdef->def.series.incr, tdef->def.series.end);
X break;
X }
X case TIC_USER: {
X register struct ticmark *t;
X fprintf(fp, " (");
X for (t = tdef->def.user; t != NULL; t=t->next) {
X if (t->label)
X fprintf(fp, "\"%s\" ", t->label);
X if (t->next)
X fprintf(fp, "%g, ", t->position);
X else
X fprintf(fp, "%g", t->position);
X }
X fprintf(fp, ")");
X break;
X }
X }
X fprintf(fp, "\n");
X } else {
X fprintf(fp,"set no%ctics\n", axis);
X }
}
X
load_file(fp, name)
X FILE *fp;
X char *name;
{
X register int len;
X extern char input_line[];
X
X int start, left;
X int more;
X int stop = FALSE;
X
X lf_push(fp); /* save state for errors and recursion */
X
X if (fp == (FILE *)NULL) {
X char errbuf[BUFSIZ];
X (void) sprintf(errbuf, "Cannot open load file '%s'", name);
X os_error(errbuf, c_token);
X } else {
X /* go into non-interactive mode during load */
X /* will be undone below, or in load_file_error */
X interactive = FALSE;
X inline_num = 0;
X infile_name = name;
X
X while (!stop) { /* read all commands in file */
X /* read one command */
X left = MAX_LINE_LEN;
X start = 0;
X more = TRUE;
X
X while (more) {
X if (fgets(&(input_line[start]), left, fp) == NULL) {
X stop = TRUE; /* EOF in file */
X input_line[start] = '\0';
X more = FALSE;
X } else {
X inline_num++;
X len = strlen(input_line) - 1;
X if (input_line[len] == '\n') { /* remove any newline */
X input_line[len] = '\0';
X /* Look, len was 1-1 = 0 before, take care here! */
X if (len > 0) --len;
X } else if (len+1 >= left)
X int_error("Input line too long",NO_CARET);
X
X if (input_line[len] == '\\') { /* line continuation */
X start = len;
X left = MAX_LINE_LEN - start; /* left -=len;*/
X } else
X more = FALSE;
X }
X }
X
X if (strlen(input_line) > 0) {
X screen_ok = FALSE; /* make sure command line is
X echoed on error */
X do_line();
X }
X }
X }
X
X /* pop state */
X (void) lf_pop(); /* also closes file fp */
}
X
/* pop from load_file state stack */
static BOOLEAN /* FALSE if stack was empty */
lf_pop() /* called by load_file and load_file_error */
{
X LFS *lf;
X
X if (lf_head == NULL)
X return(FALSE);
X else {
X lf = lf_head;
X if (lf->fp != (FILE *)NULL)
X (void) fclose(lf->fp);
X interactive = lf->interactive;
X inline_num = lf->inline_num;
X infile_name = lf->name;
X lf_head = lf->prev;
X free((char *)lf);
X return(TRUE);
X }
}
X
/* push onto load_file state stack */
/* essentially, we save information needed to undo the load_file changes */
static void
lf_push(fp) /* called by load_file */
X FILE *fp;
{
X LFS *lf;
X
X lf = (LFS *)alloc(sizeof(LFS), (char *)NULL);
X if (lf == (LFS *)NULL) {
X if (fp != (FILE *)NULL)
X (void) fclose(fp); /* it won't be otherwise */
X int_error("not enough memory to load file", c_token);
X }
X
X lf->fp = fp; /* save this file pointer */
X lf->name = infile_name; /* save current name */
X lf->interactive = interactive; /* save current state */
X lf->inline_num = inline_num; /* save current line number */
X lf->prev = lf_head; /* link to stack */
X lf_head = lf;
}
X
load_file_error() /* called from main */
{
X /* clean up from error in load_file */
X /* pop off everything on stack */
X while(lf_pop())
X ;
}
X
/* find char c in string str; return p such that str[p]==c;
X * if c not in str then p=strlen(str)
X */
int
instring(str, c)
X char *str;
X char c;
{
X int pos = 0;
X
X while (str != NULL && *str != '\0' && c != *str) {
X str++;
X pos++;
X }
X return (pos);
}
X
show_functions()
{
register struct udft_entry *udf = first_udf;
X
X fprintf(stderr,"\n\tUser-Defined Functions:\n");
X
X while (udf) {
X if (udf->definition)
X fprintf(stderr,"\t%s\n",udf->definition);
X else
X fprintf(stderr,"\t%s is undefined\n",udf->udf_name);
X udf = udf->next_udf;
X }
}
X
X
show_at()
{
X (void) putc('\n',stderr);
X disp_at(temp_at(),0);
}
X
X
disp_at(curr_at, level)
struct at_type *curr_at;
int level;
{
register int i, j;
register union argument *arg;
X
X for (i = 0; i < curr_at->a_count; i++) {
X (void) putc('\t',stderr);
X for (j = 0; j < level; j++)
X (void) putc(' ',stderr); /* indent */
X
X /* print name of instruction */
X
X fputs(ft[(int)(curr_at->actions[i].index)].f_name,stderr);
X arg = &(curr_at->actions[i].arg);
X
X /* now print optional argument */
X
X switch(curr_at->actions[i].index) {
X case PUSH: fprintf(stderr," %s\n", arg->udv_arg->udv_name);
X break;
X case PUSHC: (void) putc(' ',stderr);
X disp_value(stderr,&(arg->v_arg));
X (void) putc('\n',stderr);
X break;
X case PUSHD1: fprintf(stderr," %c dummy\n",
X arg->udf_arg->udf_name[0]);
X break;
X case PUSHD2: fprintf(stderr," %c dummy\n",
X arg->udf_arg->udf_name[1]);
X break;
X case CALL: fprintf(stderr," %s", arg->udf_arg->udf_name);
X if(level < 6) {
X if (arg->udf_arg->at) {
X (void) putc('\n',stderr);
X disp_at(arg->udf_arg->at,level+2); /* recurse! */
X } else
X fputs(" (undefined)\n",stderr);
X }
X break;
X case CALL2: fprintf(stderr," %s", arg->udf_arg->udf_name);
X if(level < 6) {
X if (arg->udf_arg->at) {
X (void) putc('\n',stderr);
X disp_at(arg->udf_arg->at,level+2); /* recurse! */
X } else
X fputs(" (undefined)\n",stderr);
X }
X break;
X case JUMP:
X case JUMPZ:
X case JUMPNZ:
X case JTERN:
X fprintf(stderr," +%d\n",arg->j_arg);
X break;
X default:
X (void) putc('\n',stderr);
X }
X }
}
X
X
/* alloc:
X * allocate memory
X * This is a protected version of malloc. It causes an int_error
X * if there is not enough memory, but first it tries FreeHelp()
X * to make some room, and tries again. If message is NULL, we
X * allow NULL return. Otherwise, we handle the error, using the
X * message to create the int_error string. Note cp/sp_extend uses realloc,
X * so it depends on this using malloc().
X */
X
char *
alloc(size, message)
X unsigned int size; /* # of bytes */
X char *message; /* description of what is being allocated */
{
X char *p; /* the new allocation */
X char errbuf[100]; /* error message string */
X
X p = malloc(size);
X if (p == (char *)NULL) {
#ifndef vms
X FreeHelp(); /* out of memory, try to make some room */
#endif
X
X p = malloc(size); /* try again */
X if (p == (char *)NULL) {
X /* really out of memory */
X if (message != NULL) {
X (void) sprintf(errbuf, "out of memory for %s", message);
X int_error(errbuf, NO_CARET);
X /* NOTREACHED */
X }
X /* else we return NULL */
X }
X }
X
X return(p);
}
SHAR_EOF
chmod 0644 gnuplot/misc.c ||
echo 'restore of gnuplot/misc.c failed'
Wc_c="`wc -c < 'gnuplot/misc.c'`"
test 22387 -eq "$Wc_c" ||
echo 'gnuplot/misc.c: original size 22387, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= gnuplot/contour.c ==============
if test -f 'gnuplot/contour.c' -a X"$1" != X"-c"; then
echo 'x - skipping gnuplot/contour.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting gnuplot/contour.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gnuplot/contour.c' &&
/* GNUPLOT - contour.c */
/*
X * Copyright (C) 1986, 1987, 1990, 1991 Thomas Williams, Colin Kelley
X *
X * Permission to use, copy, and distribute this software and its
X * documentation for any purpose with or without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and
X * that both that copyright notice and this permission notice appear
X * in supporting documentation.
X *
X * Permission to modify the software is granted, but not the right to
X * distribute the modified code. Modifications are to be distributed
X * as patches to released version.
X *
X * This software is provided "as is" without express or implied warranty.
X *
X *
X * AUTHORS
X *
X * Original Software:
X * Gershon Elber
X *
X * Send your comments or suggestions to
X * pixar!info-gnuplot@sun.com.
X * This is a mailing list; to join it send a note to
X * pixar!info-gnuplot-request@sun.com.
X * Send bug reports to
X * pixar!bug-gnuplot@sun.com.
X */
X
#include <stdio.h>
#include "plot.h"
X
#define DEFAULT_NUM_OF_ZLEVELS 10 /* Some dflt values (setable via flags). */
#define DEFAULT_NUM_APPROX_PTS 5
#define DEFAULT_BSPLINE_ORDER 3
#define MAX_NUM_OF_ZLEVELS 100 /* Some max. values (setable via flags). */
#define MAX_NUM_APPROX_PTS 100
#define MAX_BSPLINE_ORDER 10
X
#define INTERP_NOTHING 0 /* Kind of interpolations on contours. */
#define INTERP_CUBIC 1 /* Cubic spline interp. */
#define APPROX_BSPLINE 2 /* Bspline interpolation. */
X
#define ACTIVE 1 /* Status of edges at certain Z level. */
#define INACTIVE 2
X
#define OPEN_CONTOUR 1 /* Contour kinds. */
#define CLOSED_CONTOUR 2
X
#define EPSILON 1e-5 /* Used to decide if two float are equal. */
#define INFINITY 1e10
X
#ifndef TRUE
#define TRUE -1
#define FALSE 0
#endif
X
#define DEFAULT_NUM_CONTOURS 10
#define MAX_POINTS_PER_CNTR 100
#define SHIFT_Z_EPSILON 0.000301060 /* Dec. change of poly bndry hit.*/
X
#define abs(x) ((x) > 0 ? (x) : (-(x)))
#define sqr(x) ((x) * (x))
X
typedef double tri_diag[3]; /* Used to allocate the tri-diag matrix. */
typedef double table_entry[4]; /* Cubic spline interpolation 4 coef. */
X
struct vrtx_struct {
X double X, Y, Z; /* The coordinates of this vertex. */
X struct vrtx_struct *next; /* To chain lists. */
};
X
struct edge_struct {
X struct poly_struct *poly[2]; /* Each edge belongs to up to 2 polygons. */
X struct vrtx_struct *vertex[2]; /* The two extreme points of this vertex. */
X struct edge_struct *next; /* To chain lists. */
X int status, /* Status flag to mark edges in scanning at certain Z level. */
X boundary; /* True if this edge is on the boundary. */
};
X
struct poly_struct {
X struct edge_struct *edge[3]; /* As we do triangolation here... */
X struct poly_struct *next; /* To chain lists. */
};
X
struct cntr_struct { /* Contours are saved using this struct list. */
X double X, Y; /* The coordinates of this vertex. */
X struct cntr_struct *next; /* To chain lists. */
};
X
static int test_boundary; /* If TRUE look for contours on boundary first. */
static struct gnuplot_contours *contour_list = NULL;
static double crnt_cntr[MAX_POINTS_PER_CNTR * 2];
static int crnt_cntr_pt_index = 0;
static double contour_level = 0.0;
static table_entry *hermit_table = NULL; /* Hold hermite table constants. */
static int num_of_z_levels = DEFAULT_NUM_OF_ZLEVELS; /* # Z contour levels. */
static int num_approx_pts = DEFAULT_NUM_APPROX_PTS;/* # pts per approx/inter.*/
static int bspline_order = DEFAULT_BSPLINE_ORDER; /* Bspline order to use. */
static int interp_kind = INTERP_NOTHING; /* Linear, Cubic interp., Bspline. */
X
static void gen_contours();
static int update_all_edges();
static struct cntr_struct *gen_one_contour();
static struct cntr_struct *trace_contour();
static struct cntr_struct *update_cntr_pt();
static int fuzzy_equal();
static void gen_triangle();
static struct vrtx_struct *gen_vertices();
static struct edge_struct *gen_edges_middle();
static struct edge_struct *gen_edges();
static struct poly_struct *gen_polys();
static void free_contour();
static void put_contour();
static put_contour_nothing();
static put_contour_cubic();
static put_contour_bspline();
static calc_tangent();
static int count_contour();
static complete_spline_interp();
static calc_hermit_table();
static hermit_interp();
static prepare_spline_interp();
static int solve_tri_diag();
static gen_bspline_approx();
static double fetch_knot();
static eval_bspline();
X
/*
X * Entry routine to this whole set of contouring module.
X */
struct gnuplot_contours *contour(num_isolines, iso_lines,
X ZLevels, approx_pts, kind, order1)
int num_isolines;
struct iso_curve *iso_lines;
int ZLevels, approx_pts, kind, order1;
{
X int i;
X struct poly_struct *p_polys, *p_poly;
X struct edge_struct *p_edges, *p_edge;
X struct vrtx_struct *p_vrts, *p_vrtx;
X double x_min, y_min, z_min, x_max, y_max, z_max, z, dz, z_scale = 1.0;
X
X num_of_z_levels = ZLevels;
X num_approx_pts = approx_pts;
X bspline_order = order1 - 1;
X interp_kind = kind;
X
X contour_list = NULL;
X
X if (interp_kind == INTERP_CUBIC) calc_hermit_table();
X
X gen_triangle(num_isolines, iso_lines, &p_polys, &p_edges, &p_vrts,
X &x_min, &y_min, &z_min, &x_max, &y_max, &z_max);
X dz = (z_max - z_min) / (num_of_z_levels+1);
X /* Step from z_min+dz upto z_max-dz in num_of_z_levels times. */
X z = z_min + dz;
X crnt_cntr_pt_index = 0;
X
X for (i=0; i<num_of_z_levels; i++, z += dz) {
X contour_level = z;
X gen_contours(p_edges, z + dz * SHIFT_Z_EPSILON, x_min, x_max,
X y_min, y_max);
X }
X
X /* Free all contouring related temporary data. */
X while (p_polys) {
X p_poly = p_polys -> next;
X free (p_polys);
X p_polys = p_poly;
X }
X while (p_edges) {
X p_edge = p_edges -> next;
X free (p_edges);
X p_edges = p_edge;
X }
X while (p_vrts) {
X p_vrtx = p_vrts -> next;
X free (p_vrts);
X p_vrts = p_vrtx;
X }
X
X if (interp_kind == INTERP_CUBIC) free(hermit_table);
X
X return contour_list;
}
X
/*
X * Adds another point to the currently build contour.
X */
add_cntr_point(x, y)
double x, y;
{
X int index;
X
X if (crnt_cntr_pt_index >= MAX_POINTS_PER_CNTR-1) {
X index = crnt_cntr_pt_index - 1;
X end_crnt_cntr();
X crnt_cntr[0] = crnt_cntr[index * 2];
X crnt_cntr[1] = crnt_cntr[index * 2 + 1];
X crnt_cntr_pt_index = 1; /* Keep the last point as first of this one. */
X }
X crnt_cntr[crnt_cntr_pt_index * 2] = x;
X crnt_cntr[crnt_cntr_pt_index * 2 + 1] = y;
X crnt_cntr_pt_index++;
}
X
/*
X * Done with current contour - create gnuplot data structure for it.
X */
end_crnt_cntr()
{
X int i;
X struct gnuplot_contours *cntr = (struct gnuplot_contours *)
X alloc(sizeof(struct gnuplot_contours),
X "gnuplot_contour");
X
X cntr->coords = (struct coordinate *) alloc(sizeof(struct coordinate) *
X crnt_cntr_pt_index,
X "contour coords");
X for (i=0; i<crnt_cntr_pt_index; i++) {
X cntr->coords[i].x = crnt_cntr[i * 2];
X cntr->coords[i].y = crnt_cntr[i * 2 + 1];
X cntr->coords[i].z = contour_level;
X }
X cntr->num_pts = crnt_cntr_pt_index;
X
X cntr->next = contour_list;
X contour_list = cntr;
X
X crnt_cntr_pt_index = 0;
}
X
/*
X * Generates all contours by tracing the intersecting triangles.
X */
static void gen_contours(p_edges, z_level, x_min, x_max, y_min, y_max)
struct edge_struct *p_edges;
double z_level, x_min, x_max, y_min, y_max;
{
X int num_active, /* Number of edges marked ACTIVE. */
X contour_kind; /* One of OPEN_CONTOUR, CLOSED_CONTOUR. */
X struct cntr_struct *p_cntr;
X
X num_active = update_all_edges(p_edges, z_level); /* Do pass 1. */
X
X test_boundary = TRUE; /* Start to look for contour on boundaries. */
X
X while (num_active > 0) { /* Do Pass 2. */
X /* Generate One contour (and update MumActive as needed): */
X p_cntr = gen_one_contour(p_edges, z_level, &contour_kind, &num_active);
X put_contour(p_cntr, z_level, x_min, x_max, y_min, y_max,
X contour_kind); /* Emit it in requested format. */
X }
}
X
/*
X * Does pass 1, or marks the edges which are active (crosses this z_level)
X * as ACTIVE, and the others as INACTIVE:
X * Returns number of active edges (marked ACTIVE).
X */
static int update_all_edges(p_edges, z_level)
struct edge_struct *p_edges;
double z_level;
{
X int count = 0;
X
X while (p_edges) {
X if (((p_edges -> vertex[0] -> Z >= z_level) &&
X (p_edges -> vertex[1] -> Z <= z_level)) ||
X ((p_edges -> vertex[1] -> Z >= z_level) &&
X (p_edges -> vertex[0] -> Z <= z_level))) {
X p_edges -> status = ACTIVE;
X count++;
X }
X else p_edges -> status = INACTIVE;
X p_edges = p_edges -> next;
X }
X
X return count;
}
X
/*
X * Does pass 2, or find one complete contour out of the triangolation data base:
X * Returns a pointer to the contour (as linked list), contour_kind is set to
X * one of OPEN_CONTOUR, CLOSED_CONTOUR, and num_active is updated.
X */
static struct cntr_struct *gen_one_contour(p_edges, z_level, contour_kind,
X num_active)
struct edge_struct *p_edges;
double z_level;
int *contour_kind, *num_active;
{
X struct edge_struct *pe_temp;
X
X if (test_boundary) { /* Look for something to start with on boundary: */
X pe_temp = p_edges;
X while (pe_temp) {
X if ((pe_temp -> status == ACTIVE) && (pe_temp -> boundary)) break;
X pe_temp = pe_temp -> next;
X }
X if (!pe_temp) test_boundary = FALSE;/* No more contours on boundary. */
X else {
X *contour_kind = OPEN_CONTOUR;
X return trace_contour(pe_temp, z_level, num_active, *contour_kind);
X }
X }
X
X if (!test_boundary) { /* Look for something to start with inside: */
X pe_temp = p_edges;
X while (pe_temp) {
X if ((pe_temp -> status == ACTIVE) && (!(pe_temp -> boundary)))
X break;
X pe_temp = pe_temp -> next;
X }
X if (!pe_temp) {
X *num_active = 0;
X return NULL;
X }
X else {
X *contour_kind = CLOSED_CONTOUR;
X return trace_contour(pe_temp, z_level, num_active, *contour_kind);
X }
X }
X return NULL; /* We should never be here, but lint... */
}
X
/*
X * Search the data base along a contour starts at the edge pe_start until
X * a boundary edge is detected or until we close the loop back to pe_start.
X * Returns a linked list of all the points on the contour
X * Also decreases num_active by the number of points on contour.
X */
static struct cntr_struct *trace_contour(pe_start, z_level, num_active,
X contour_kind)
struct edge_struct *pe_start;
double z_level;
int *num_active, contour_kind;
{
X int i, in_middle; /* If TRUE the z_level is in the middle of edge. */
X struct cntr_struct *p_cntr, *pc_tail;
X struct edge_struct *p_edge = pe_start, *p_next_edge;
X struct poly_struct *p_poly, *PLastpoly = NULL;
X
X /* Generate the header of the contour - the point on pe_start. */
X if (contour_kind == OPEN_CONTOUR) pe_start -> status = INACTIVE;
X (*num_active)--;
X p_cntr = pc_tail = update_cntr_pt(pe_start, z_level, &in_middle);
X if (!in_middle) {
X return NULL;
X }
X
X do {
X /* Find polygon to continue (Not where we came from - PLastpoly): */
X if (p_edge -> poly[0] == PLastpoly) p_poly = p_edge -> poly[1];
X else p_poly = p_edge -> poly[0];
X p_next_edge = NULL; /* In case of error, remains NULL. */
X for (i=0; i<3; i++) /* Test the 3 edges of the polygon: */
X if (p_poly -> edge[i] != p_edge)
X if (p_poly -> edge[i] -> status == ACTIVE)
X p_next_edge = p_poly -> edge[i];
X if (!p_next_edge) {
X pc_tail -> next = NULL;
X free_contour(p_cntr);
X return NULL;
X }
X p_edge = p_next_edge;
X PLastpoly = p_poly;
X p_edge -> status = INACTIVE;
X (*num_active)--;
X pc_tail -> next = update_cntr_pt(p_edge, z_level, &in_middle);
X if (!in_middle) {
X pc_tail -> next = NULL;
X free_contour(p_cntr);
X return NULL;
X }
X pc_tail = pc_tail -> next;
X }
X while ((pe_start != p_edge) && (!p_edge -> boundary));
X pc_tail -> next = NULL;
X
X return p_cntr;
}
X
/*
X * Allocates one contour location and update it to to correct position
X * according to z_level and edge p_edge. if z_level is found to be at
X * one of the extreme points nothing is allocated (NULL is returned)
X * and in_middle is set to FALSE.
X */
static struct cntr_struct *update_cntr_pt(p_edge, z_level, in_middle)
struct edge_struct *p_edge;
double z_level;
int *in_middle;
{
X double t;
X struct cntr_struct *p_cntr;
X
X t = (z_level - p_edge -> vertex[0] -> Z) /
X (p_edge -> vertex[1] -> Z - p_edge -> vertex[0] -> Z);
X
X if (fuzzy_equal(t, 1.0) || fuzzy_equal(t, 0.0)) {
X *in_middle = FALSE;
X return NULL;
X }
X else {
X *in_middle = TRUE;
X p_cntr = (struct cntr_struct *) alloc(sizeof(struct cntr_struct),
SHAR_EOF
true || echo 'restore of gnuplot/contour.c failed'
fi
echo 'End of part 4'
echo 'File gnuplot/contour.c is continued in part 5'
echo 5 > _shar_seq_.tmp
exit 0
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.