/* ======================================================= *
* Copyright 1998-2005 Stephen C. Grubb *
* http://ploticus.sourceforge.net *
* Covered by GPL; see the file ./Copyright for details. *
* ======================================================= */
/* windbarb features contributed by Andrew Phillips */
/* PROC VECTOR - render a display of vectors */
#include "pl.h"
#define TWOPI 6.2831854
#define HALFPI 1.5707963
int
PLP_vector()
{
int i;
char attr[NAMEMAXLEN], val[256];
char *line, *lineval;
int nt, lvp;
int first, stat;
int xfield, yfield, dirfield, magfield, colorfield, exactcolorfield, clip;
double dirrange, lenscale, x, y, newx, newy, len, dir, ahlen, ahwid;
double sin(), cos(), basedir, constantlen, holdx, holdy;
char acolor[COLORLEN], linedetails[128], legendlabel[256], selex[128];
double barblimitbig, barblimitmedium, barblimitsmall, barblimittiny, barbdir, mag;
char dirunits, zeroat, clockdir, lenunits, type;
int x2field, y2field;
double taillen;
TDH_errprog( "pl proc vector" );
xfield = -1;
yfield = -1;
dirfield = -1;
magfield = -1;
colorfield = -1;
exactcolorfield = -1;
dirrange = 360.0;
ahlen = 0.15;
ahwid = 0.4;
strcpy( acolor, "" );
strcpy( selex, "" );
strcpy( legendlabel, "" );
strcpy( linedetails, "" );
dirunits = 'd'; /* degrees */
zeroat = 't'; /* top */
clockdir = '+'; /* clockwise */
lenunits = 'a'; /* absolute */
type = 'a'; /* arrow */
lenscale = 1.0;
constantlen = 0.0;
clip = 1;
x2field = -1;
y2field = -1;
taillen = 0.1;
barblimitbig = 50.0; /* Magnitude limits */
barblimitmedium = 10.0;
barblimitsmall = 5.0;
barblimittiny = 2.0;
barbdir = 120;
mag = 0;
/* get attributes.. */
first = 1;
while( 1 ) {
line = getnextattr( first, attr, val, &lvp, &nt );
if( line == NULL ) break;
first = 0;
lineval = &line[lvp];
if( stricmp( attr, "xfield" )==0 ) xfield = fref( val ) -1;
else if( stricmp( attr, "yfield" )==0 ) yfield = fref( val ) -1;
else if( stricmp( attr, "dirfield" )==0 ) dirfield = fref( val ) -1;
else if( stricmp( attr, "x2field" )==0 ) x2field = fref( val ) -1;
else if( stricmp( attr, "y2field" )==0 ) y2field = fref( val ) -1;
else if( stricmp( attr, "dirrange" )==0 ) dirrange = atof( val );
else if( stricmp( attr, "dirunits" )==0 ) dirunits = tolower( val[0] );
else if( stricmp( attr, "clockdir" )==0 ) clockdir = tolower( val[0] );
else if( stricmp( attr, "zeroat" )==0 ) zeroat = tolower( val[0] );
else if( stricmp( attr, "magfield" )==0 ) magfield = fref( val ) -1;
else if( stricmp( attr, "lenfield" )==0 ) magfield = fref( val ) -1; /* Alias */
else if( stricmp( attr, "lenunits" )==0 ) lenunits = tolower( val[0] );
else if( stricmp( attr, "lenscale" )==0 ) lenscale = atof( val );
else if( stricmp( attr, "constantlen" )==0 ) constantlen = atof( val );
else if( stricmp( attr, "colorfield" )==0 ) colorfield = fref( val ) -1;
else if( stricmp( attr, "exactcolorfield" )==0 ) exactcolorfield = fref( val ) -1;
else if( stricmp( attr, "linedetails" )==0 ) strcpy( linedetails, lineval );
else if( stricmp( attr, "arrowheadlength" )==0 ) ahlen = atof( val );
else if( stricmp( attr, "arrowheadwidth" )==0 ) ahwid = atof( val );
else if( stricmp( attr, "arrowheadcolor" )==0 ) strcpy( acolor, val );
else if( stricmp( attr, "select" )==0 ) strcpy( selex, lineval );
else if( stricmp( attr, "legendlabel" )==0 ) strcpy( legendlabel, lineval );
else if( stricmp( attr, "taillen" )==0 ) taillen = atof( val );
else if( stricmp( attr, "clip" )==0 ) {
if( strnicmp( val, YESANS, 1 )==0 ) clip = 1;
else clip = 0;
}
else if( stricmp( attr, "type" )==0 ) type = tolower( val[0] );
else if( stricmp( attr, "barblimits" )==0 ) {
sscanf( lineval, "%lf %lf %lf %lf",
&barblimitbig, &barblimitmedium, &barblimitsmall, &barblimittiny );
}
else if( stricmp( attr, "barbdir" )==0 ) barbdir = atof( val );
else Eerr( 1, "attribute not recognized", attr );
}
/* overrides and degenerate cases */
/* -------------------------- */
if( Nrecords < 1 ) return( Eerr( 17, "No data has been read yet w/ proc getdata", "" ) );
if( !scalebeenset() )
return( Eerr( 51, "No scaled plotting area has been defined yet w/ proc areadef", "" ) );
if( type == 'e' ) type = 'i';
if( xfield < 0 || yfield < 0 ) return( Eerr( 2205, "xfield and yfield are both required", "" ));
if( dirfield < 0 && ( x2field < 0 || y2field < 0 )) return( Eerr( 2205, "dirfield or x2field&y2field required", "" ));
if( magfield < 0 && constantlen == 0.0 && (x2field < 0 || y2field < 0 ))
return( Eerr( 2205, "magfield, constantlen, or x2field&y2field required", "" ));
if( magfield < 0 && type == 'b' && (x2field < 0 || y2field < 0 ))
return( Eerr( 2205, "magfield oe x2field/y2field required when type is barb", "" ));
if( barblimitbig <= 0 || barblimitmedium <= 0 || barblimitsmall <= 0 ) return( Eerr( 2205, "barblimits must be grater then 0", ""));
if( strnicmp( legendlabel, "#usefname", 9 )==0 ) getfname( dirfield+1, legendlabel );
if( !GL_member( type, "abelit" )) type = 'a';
/* now do the plotting work.. */
/* -------------------------- */
if( dirunits == 'r' ) dirrange = TWOPI;
if( zeroat == 't' ) basedir = TWOPI * 0.25; /* top */
else if( zeroat == 'b' ) basedir = TWOPI * 0.75; /* bottom */
else if( zeroat == 'l' ) basedir = TWOPI * 0.5; /* left */
linedet( "linedetails", linedetails, 0.5 );
barbdir = (barbdir/dirrange) * TWOPI;
for( i = 0; i < Nrecords; i++ ) {
if( selex[0] != '\0' ) { /* process against selection condition if any.. */
int result;
stat = do_select( selex, i, &result );
if( stat != 0 ) { Eerr( stat, "Select error", selex ); continue; }
if( result == 0 ) continue; /* reject */
}
/* get x value.. */
x = fda( i, xfield, 'x' );
if( Econv_error() ) { conv_msg( i, xfield, "xfield" ); continue; }
/* get y value.. */
y = fda( i, yfield, 'y' );
if( Econv_error() ) { conv_msg( i, yfield, "yfield" ); continue; }
/* if colorfield used, get color.. */
if( colorfield >= 0 ) {
strcpy( linedetails, "" );
PL_get_legent( da( i, colorfield ), linedetails, NULL, NULL );
linedet( "colorfield", linedetails, 0.5 );
}
else if( exactcolorfield >= 0 ) {
strcpy( linedetails, da( i, exactcolorfield ) );
linedet( "exactcolorfield", linedetails, 0.5 );
}
/* convert x,y to absolute units.. */
x = Eax( x );
y = Eay( y );
/* added scg 12/19/03 */
if( x2field >= 0 && y2field >=0 ) {
newx = Eax( fda( i, x2field, 'x' ) );
newy = Eay( fda( i, y2field, 'y' ) );
}
else {
/* dir and len.. */
dir = atof( da( i, dirfield ) );
if( magfield >= 0 ) mag = atof( da( i, magfield ) );
if( constantlen > 0.0 ) len = constantlen;
/* else len = atof( da( i, magfield ) ); */
else len = mag;
if( clockdir == '+' ) dir *= -1.0;
/* normalize dir and len.. */
dir = basedir + ((dir / dirrange) * TWOPI );
len *= lenscale;
if( lenunits == 'x' || lenunits == 'd' || lenunits == 'u' ) len = Eax( len ) - Eax( 0.0 );
else if( lenunits == 'y' ) len = Eay( len ) - Eay( 0.0 );
newx = x + (len * cos( dir ));
newy = y + (len * sin( dir ));
}
/* skip degenerate cases.. added scg 5/24/05 */
if( x == newx && y == newy ) continue;
if( clip ) {
holdx = newx; holdy = newy;
stat = Elineclip( &x, &y, &newx, &newy, EXlo, EYlo, EXhi, EYhi );
if( stat ) continue; /* entire vector is out of range */
else if( ! GL_close_to( newx, holdx, 0.000001 ) || !GL_close_to( newy, holdy, 0.000001 ) ) {
/* end is out of range, just draw line.. */
Emov( x, y );
Elin( newx, newy );
continue;
}
}
/* arrow */
if( type == 'a' ) {
Earrow( x, y, newx, newy, ahlen, ahwid, acolor );
}
/* line or error bar */
else if( type == 'l' || type == 'i' || type == 't' ) {
Emov( x, y );
Elin( newx, newy );
if( type == 'i' ) PLG_perptail( x, y, newx, newy, taillen );
if( type == 'i' || type == 't' ) PLG_perptail( newx, newy, x, y, taillen );
}
/* windbarb */
else if( type == 'b' ) {
/* contributed by Andrew Phillips */
int bigBarbCount, mediumBarbCount, smallBarbCount, curBarb, b;
double x1, x2, x3, y1, y2, y3, newMag, barbLen, barbSpace, barbAdjust;
bigBarbCount = 0;
mediumBarbCount = 0;
smallBarbCount = 0;
curBarb = 0;
newMag = mag;
/* length of barbs and the space betwen them */
barbLen = len/3;
barbSpace = len/6;
/* used to make small and medium barbs come from the
end of them stem */
barbAdjust = 0;
if( newMag >= barblimittiny) {
/* Draw the stem */
Emov( x, y );
Elin( newx, newy );
/* Count how many barbs to draw. Since barblimitbig
and friends arn't always going to be integers we
have to do this insted of some modulo fun. */
while(newMag > barblimitbig) {
bigBarbCount++;
newMag -= barblimitbig;
}
while(newMag > barblimitmedium) {
mediumBarbCount++;
newMag -= barblimitmedium;
}
while(newMag > barblimitsmall) {
smallBarbCount++;
newMag -= barblimitsmall;
}
/* Draw the big (triangle) barbs */
for (b = 0; b < bigBarbCount && curBarb < 8; b++) {
x1 = x + ((len - curBarb*barbSpace) * cos( dir ));
y1 = y + ((len - curBarb*barbSpace) * sin( dir ));
x2 = x + ((len - (curBarb+0.5)*barbSpace) * cos( dir )) - (barbLen * cos(dir+barbdir));
y2 = y + ((len - (curBarb+0.5)*barbSpace) * sin( dir )) - (barbLen * sin(dir+barbdir));
x3 = x + ((len - (curBarb+1)*barbSpace) * cos( dir ));
y3 = y + ((len - (curBarb+1)*barbSpace) * sin( dir ));
Emov(x1, y1);
Epath(x2, y2);
Epath(x3, y3);
Epath(x1, y1);
Ecolorfill( Ecurcolor );
curBarb++;
}
if (bigBarbCount > 0) barbAdjust = 0.5;
/* Draw the medium barbs */
for (b = 0; b < mediumBarbCount && curBarb < 8; b++) {
x1 = x + ((len - (curBarb+barbAdjust)*barbSpace) * cos( dir ));
y1 = y + ((len - (curBarb+barbAdjust)*barbSpace) * sin( dir ));
x2 = x1 - (barbLen * cos(dir+barbdir));
y2 = y1 - (barbLen * sin(dir+barbdir));
Emov(x1, y1);
Elin(x2, y2);
curBarb++;
}
/* Draw the small barbs */
for (b = 0; b < smallBarbCount && curBarb < 8; b++) {
x1 = x + ((len - (curBarb+barbAdjust)*barbSpace) * cos( dir ));
y1 = y + ((len - (curBarb+barbAdjust)*barbSpace) * sin( dir ));
x2 = x1 - (barbLen/2 * cos(dir+barbdir));
y2 = y1 - (barbLen/2 * sin(dir+barbdir));
Emov(x1, y1);
Elin(x2, y2);
curBarb++;
}
}
else {
/* Tiny barbs should just be half length stems */
newx = x + (len/2 * cos( dir ));
newy = y + (len/2 * sin( dir ));
/* Draw the mini stem */
Emov( x, y );
Elin( newx, newy );
}
} /* end of barbs */
} /* end data rows loop */
if( legendlabel[0] != '\0' ) PL_add_legent( LEGEND_LINE, legendlabel, "", linedetails, "", "" );
return( 0 );
}
/* ======================================================= *
* Copyright 1998-2005 Stephen C. Grubb *
* http://ploticus.sourceforge.net *
* Covered by GPL; see the file ./Copyright for details. *
* ======================================================= */
syntax highlighted by Code2HTML, v. 0.9.1