Hi Hartmut,
> thanks for your previous help. I have it all going now except for one small
> detail:
>
> Many of the concentrations are very small (e.g. 1e-6 range), and it appears
> to me that the labeling on the axis shows "0" for both low and high values
> whenever the high is <0.001.
>
> Is it possible to either switch the labeling to scientific notation when
> the maximum is smaller than 0.001 or use scientific notation at all times?
Good suggestion. I have made this change in the attached
PlotText.java, which you can use to replace the one in your
visad directory. It will show up in the ftp distribution
the next time we update it.
Cheers,
Bill
----------------------------------------------------------
Bill Hibbard, SSEC, 1225 W. Dayton St., Madison, WI 53706
hibbard@xxxxxxxxxxxxxxxxx 608-263-4427 fax: 608-263-6738
http://www.ssec.wisc.edu/~billh/vis.html
//
// PlotText.java
//
/*
VisAD system for interactive analysis and visualization of numerical
data. Copyright (C) 1996 - 2000 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/
package visad;
import visad.*;
/**
PlotText calculates an array of points to be plotted to
the screen as vector pairs, given a String and location,
orientation and size in space.<P>
The font is a simple one, and includes characters from
the ASCII collating sequence from 0x20 thru 0x7E.
Most of this was taken from the original visad.PlotText.
*/
public class PlotText extends Object {
static final double XMIN = -1.0;
static final double YMIN = -1.0;
static final double ZMIN = -1.0;
static final double WIDTH = .8;
/* base line and up vectors */
static double[] bx = { 0.07, 0.0, 0.0 }, ux = { 0.0, 0.07, 0.07 };
static double[] by = { 0.0, 0.07, 0.0 }, uy = { -0.07, 0.0, -0.07 };
static double[] bz = { 0.0, 0.0, -0.07 }, uz = { 0.07, 0.07, 0.0 };
/* vector characters -- (100 + x) value indicates beginning of segment */
/* characters are ordered by ASCII collating sequence, starting at 0x20 */
static float[][] charCodes = {
{100f,0f}, // sp
{101f,8f,1f,3f,3f,3f,3f,8f,1f,8f,101f,1f,1f,0f,3f,0f,3f,1f,1f,1f}, // !
{101f,8f,0f,5f,104f,8f,3f,5f}, // "
{101.5f,8f,1.5f,0f,103.5f,8f,3.5f,0f,100f,5f,5f,5f,100f,3f,5f,3f}, // #
{101.5f,8f,1.5f,0f,102.5f,8f,2.5f,0f,104f,5.5f,3f,7f,1f,7f,0f,5.5f,0f,4.5f,4f,3.5f,4f,2.5f,3f,1f,1f,1f,0f,2.5f},
// $
{100f,8f,0f,7f,1f,7f,1f,8f,0f,8f,105f,8f,0f,0f,104f,1f,4f,0f,5f,0f,5f,1f,4f,1f},
// %
{105f,0f,0f,5f,0f,7f,1f,8f,3f,8f,4f,7f,4f,5f,0f,3f,0f,1f,1f,0f,3f,0f,5f,3f,5f,4f},
// &
{101f,8f,0f,5f}, // '
{104f,8f,2f,6f,2f,2f,4f,0f}, // (
{101f,8f,3f,6f,3f,2f,1f,0f}, // )
{100f,7f,5f,1f,102.5f,7f,2.5f,1f,100f,1f,5f,7f,105f,4f,0f,4f}, // *
{102.5f,7f,2.5f,1f,100f,4f,5f,4f}, // +
{103f,0f,2f,0f,2f,1f,3f,1f,3f,0f,2.1f,-2f}, // ,
{100f,4f,5f,4f}, // -
{102f,0f,3f,0f,3f,1f,2f,1f,2f,0f}, // .
{100f,0f,5f,8f}, // /
{102f,8f,0f,6f,0f,2f,2f,0f,3f,0f,5f,2f,5f,6f,3f,8f,2f,8f}, // 0
{101f,7f,2.5f,8f,2.5f,0f,1f,0f,4f,0f}, // 1
{100f,7f,1f,8f,4f,8f,5f,7f,5f,5f,0f,0f,5f,0f}, // 2
{100f,7f,1f,8f,4f,8f,5f,7f,5f,5f,4f,4f,3f,4f,4f,4f,5f,3f,5f,1f,4f,0f,1f,0f,0f,1f},
// 3
{103f,8f,0f,4f,5f,4f,5f,8f,5f,0f}, // 4
{100f,1f,1f,0f,4f,0f,5f,1f,5f,4f,4f,5f,0f,5f,0f,8f,5f,8f}, // 5
{105f,7f,4f,8f,1f,8f,0f,7f,0f,1f,1f,0f,4f,0f,5f,1f,5f,3f,4f,4f,0f,4f},
// 6
{100f,8f,5f,8f,3f,0f}, // 7
{101f,8f,0f,7f,0f,5f,1f,4f,4f,4f,5f,5f,5f,7f,4f,8f,1f,8f,101f,4f,0f,3f,0f,1f,1f,0f,4f,0f,5f,1f,5f,3f,4f,4f},
// 8
{101f,0f,1f,0f,4f,0f,5f,1f,5f,7f,4f,8f,1f,8f,0f,7f,0f,5f,1f,4f,5f,4f},
// 9
{102f,7f,2f,5f,3f,5f,3f,7f,2f,7f,102f,3f,2f,1f,3f,1f,3f,3f,2f,3f}, // :
{100f,7f,0f,5f,1f,5f,1f,7f,0f,7f,100f,0f,1f,1f,1f,3f,0f,3f,0f,1f,1f,1f}, // ;
{105f,7f,0f,4f,5f,1f}, // <
{100f,5f,5f,5f,100f,3f,5f,3f}, // =
{100f,7f,5f,4f,0f,1f}, // >
{100f,7f,1f,8f,4f,8f,5f,7f,5f,5f,4f,4f,2.5f,4f,2.5f,2f,102.5f,1f,2.5f,0f}, // ?
{104f,0f,1f,0f,0f,1f,0f,7f,1f,8f,4f,8f,5f,7f,5f,3f,4f,1.5f,3f,2f,1.5f,4f,1.5f,5f,2.5f,6f,4f,5f,3f,2f},
// @
{100f,0f,0f,7f,1f,8f,4f,8f,5f,7f,5f,0f,5f,4f,0f,4f}, // A
{100f,8f,0f,0f,4f,0f,5f,1f,5f,3f,4f,4f,5f,5f,5f,7f,4f,8f,0f,8f,0f,4f,4f,4f}, //
B
{105f,7f,4f,8f,1f,8f,0f,7f,0f,1f,1f,0f,4f,0f,5f,1f}, // C
{100f,8f,0f,0f,4f,0f,5f,1f,5f,7f,4f,8f,0f,8f}, // D
{105f,8f,0f,8f,0f,4f,3f,4f,0f,4f,0f,0f,5f,0f}, // E
{105f,8f,0f,8f,0f,4f,3f,4f,0f,4f,0f,0f}, // F
{105f,7f,4f,8f,1f,8f,0f,7f,0f,1f,1f,0f,4f,0f,5f,1f,5f,4f,3f,4f}, // G
{100f,8f,0f,0f,0f,4f,5f,4f,5f,8f,5f,0f}, // H
{100f,8f,5f,8f,2.5f,8f,2.5f,0f,0f,0f,5f,0f}, // I
{105f,8f,5f,1f,4f,0f,1f,0f,0f,1f,0f,3f}, // J
{100f,8f,0f,0f,0f,4f,5f,8f,0f,4f,5f,0f}, // K
{100f,8f,0f,0f,5f,0f}, // L
{100f,0f,0f,8f,2.5f,4f,5f,8f,5f,0f}, // M
{100f,0f,0f,8f,5f,0f,5f,8f}, // N
{101f,8f,0f,7f,0f,1f,1f,0f,4f,0f,5f,1f,5f,7f,4f,8f,1f,8f}, // O
{100f,0f,0f,8f,4f,8f,5f,7f,5f,5f,4f,4f,0f,4f}, // P
{101f,8f,0f,7f,0f,1f,1f,0f,4f,0f,5f,1f,5f,7f,4f,8f,1f,8f,103f,3f,5f,0f}, // Q
{100f,0f,0f,8f,4f,8f,5f,7f,5f,5f,4f,4f,0f,4f,3f,4f,5f,0f}, // R
{105f,7f,4f,8f,1f,8f,0f,7f,0f,5f,1f,4f,4f,4f,5f,3f,5f,1f,4f,0f,1f,0f,0f,1f}, //
S
{100f,8f,5f,8f,2.5f,8f,2.5f,0f}, // T
{100f,8f,0f,1f,1f,0f,4f,0f,5f,1f,5f,8f}, // U
{100f,8f,2.5f,0f,5f,8f}, // V
{100f,8f,0f,0f,2.5f,4f,5f,0f,5f,8f}, // W
{100f,8f,5f,0f,100f,0f,5f,8f}, // X
{100f,8f,2.5f,4f,5f,8f,2.5f,4f,2.5f,0f}, // Y
{100f,8f,5f,8f,0f,0f,5f,0f}, // Z
{104f,8f,2f,8f,2f,0f,4f,0f}, // [
{100f,8f,5f,0f}, // \
{101f,8f,3f,8f,3f,0f,1f,0f}, // ]
{102f,6f,3f,8f,4f,6f}, // ^
{100f,-2f,5f,-2f}, // _
{102f,8f,4f,6f}, // `
{104f,5f,4f,1f,3f,0f,1f,0f,0f,1f,0f,4f,1f,5f,3f,5f,4f,4f,4f,1f,5f,0f},
// a
{100f,8f,0f,0f,0f,1f,1f,0f,4f,0f,5f,1f,5f,4f,4f,5f,3f,5f,0f,3f}, // b
{105f,0f,1f,0f,0f,1f,0f,4f,1f,5f,4f,5f,5f,4f}, // c
{105f,3f,3f,5f,1f,5f,0f,4f,0f,1f,1f,0f,4f,0f,5f,1f,5f,0f,5f,8f}, // d
{105f,0f,1f,0f,0f,1f,0f,4f,1f,5f,4f,5f,5f,4f,4f,3f,0f,3f}, // e
{103f,0f,3f,7f,4f,8f,5f,8f,5f,7f,101f,4f,4f,4f}, // f
{105f,5f,5f,-3f,4f,-4f,1f,-4f,105f,1f,4f,0f,1f,0f,0f,1f,0f,4f,1f,5f,3f,5f,5f,3f},
// g
{100f,8f,0f,0f,0f,3f,3f,5f,4f,5f,5f,4f,5f,0f}, // h
{103f,4f,3f,0f,4f,0f,1f,0f,103f,6.5f,3f,5.5f}, // i
{104f,4f,4f,-3f,3f,-4f,1f,-4f,0f,-3f,0f,-1f,1f,0f,104f,6.5f,4f,5.5f},
// j
{101f,8f,1f,0f,101f,3f,5f,5f,101f,3f,5f,0f}, // k
{102f,8f,3f,8f,3f,0f}, // l
{100f,0f,0f,5f,0f,4f,1f,5f,4f,5f,5f,4f,5f,0f,102.5f,5f,2.5f,2.0f}, // m
{100f,0f,0f,5f,0f,4f,1f,5f,4f,5f,5f,3f,5f,0f}, // n
{101f,0f,0f,1f,0f,4f,1f,5f,4f,5f,5f,4f,5f,1f,4f,0f,1f,0f}, // o
{100f,-4f,0f,1f,1f,0f,4f,0f,5f,1f,5f,4f,4f,5f,3f,5f,0f,3f,0f,1f,0f,5f},
// p
{105f,-4f,5f,1f,4f,0f,1f,0f,0f,1f,0f,4f,1f,5f,3f,5f,5f,3f,5f,1f,5f,5f},
// q
{100f,5f,0f,0f,0f,3f,3f,5f,4f,5f,5f,4f}, // r
{105f,4f,3f,5f,2f,5f,0f,4f,0f,3f,5f,2f,5f,1f,3f,0f,2f,0f,0f,1f}, // s
// {105f,4f,4f,5f,3f,5f,1f,3.5f,3f,3f,4f,3f,5f,1f,4f,0f,3f,0f,1f,1f},
// s
{102.5f,8f,2.5f,0f,100.5f,5f,4.5f,5f}, // t
{100f,5f,0f,1f,1f,0f,3f,0f,5f,3f,5f,5f,5f,0f}, // u
{100f,5f,0f,3f,2.5f,0f,5f,3f,5f,5f}, // v
{100f,5f,0f,0f,2.5f,3f,5f,0f,5f,5f}, // w
{100f,5f,5f,0f,105f,5f,0f,0f}, // x
{100f,5f,0f,3f,3f,0f,5f,3f,5f,5f,5f,-3f,3f,-4f}, // y
{100f,5f,5f,5f,0f,0f,5f,0f}, // z
{104f,8f,3f,8f,2f,4.5f,1f,4.5f,2f,4.5f,3f,0f,4f,0f}, // {
{103.5f,8f,3.5f,0f}, // |
{102f,8f,3f,8f,4f,4.5f,5f,4.5f,4f,4.5f,3f,0f,2f,0f}, // }
{100f,4f,1f,5f,3f,4f,4f,5f}, // ~
{100f,0f} // RO
};
/**
* Convert a string of characters (ASCII collating sequence) into a
* series of vectors for drawing.
*
* @param axis [=0 (x), =1 (y), or =2 (z)
* @param pos position along axis to put label in [-1,1]
* @param str the text string to "print"
* @param line line number for multi-line text (0 = first line)
* @param c color (not used yet)
*
* @return VisADLineArray of all the vectors needed to draw the
* characters in this string
*/
public static VisADLineArray render_label(int axis, double pos, String str,
int line, long c) {
double XMIN = -1.0;
double YMIN = -1.0;
double ZMIN = -1.0;
/* base line and up vectors */
double[] bx = { 0.07, 0.0, 0.0 }, ux = { 0.0, 0.07, 0.07 };
double[] by = { 0.0, 0.07, 0.0 }, uy = { -0.07, 0.0, -0.07 };
double[] bz = { 0.0, 0.0, -0.07 }, uz = { 0.07, 0.07, 0.0 };
double[] base = null;
double[] up = null;
double[] start = new double[3];
if (axis==0) { // x
base = bx;
up = ux;
start[0] = pos;
start[1] = YMIN * (1.1 + 0.07*line);
start[2] = ZMIN * (1.1 + 0.07*line);
}
else if (axis==1) { // y
base = by;
up = uy;
start[0] = XMIN * (1.1 + 0.07*line);
start[1] = pos;
start[2] = ZMIN * (1.1 + 0.07*line);
}
else if (axis==2) { // z
base = bz;
up = uz;
start[0] = XMIN * (1.1 + 0.07*line);
start[1] = YMIN * (1.1 + 0.07*line);
start[2] = pos;
}
return render_label(str, start, base, up, true);
}
/**
* Convert a string of characters (ASCII collating sequence) into a
* series of vectors for drawing.
*
* @param str String to use
* @param start point (x,y,z)
* @param base (x,y,z) of baseline vector
* @param up (x,y,z) of "up" direction vector
* @param center is <CODE>true</CODE> if string is to be centered
*
* @return VisADLineArray of all the vectors needed to draw the
* characters in this string
*/
public static VisADLineArray render_label(String str, double[] start,
double[] base, double[] up, boolean center) {
double[] temp;
double cx, cy, cz;
double startx = 0.0;
double starty = 0.0;
double startz = 0.0;
double sw;
int i, j, k, v2, len;
cx = start[0];
cy = start[1];
cz = start[2];
len = str.length();
// allow 20 2-point 3-component strokes per character
float[] plot = new float[120 * len];
if (center) {
/* calculate string width for center justify - fixed width font*/
sw = WIDTH * (float) len;
cx -= sw * base[0] / 2.0;
cy -= sw * base[1] / 2.0;
cz -= sw * base[2] / 2.0;
}
int plot_index = 0;
/* draw left justified text */
for (i=0; i<len; i++) {
k = str.charAt(i) - 32;
if (k < 0 || k > 127) continue; // invalid - just skip
int verts = charCodes[k].length/2;
/* make the vertex array for this character */
/* points with x>9 are 'start new segment' flag */
int temp_index = 0;
for (j=0; j<verts; j++) {
if (verts == 1) break; // handle space character
boolean dup_point = true;
if (j == (verts - 1) ) dup_point = false; // don't dupe last point
double x, y;
x = (double) charCodes[k][temp_index]*.1;
if (x > 9.0) {
if (j != 0) plot_index -= 3; // reset pointer to remove last point
x = x - 10.0;
dup_point = false;
}
temp_index++;
y = (double) charCodes[k][temp_index]*.1;
temp_index++;
plot[plot_index] = (float) (cx + x * base[0] + y * up[0]);
plot[plot_index + 1] = (float) (cy + x * base[1] + y * up[1]);
plot[plot_index + 2] = (float) (cz + x * base[2] + y * up[2]);
if (dup_point) { // plot points are in pairs -- set up for next pair
plot[plot_index + 3] = plot[plot_index];
plot[plot_index + 4] = plot[plot_index + 1];
plot[plot_index + 5] = plot[plot_index + 2];
plot_index += 3;
}
plot_index += 3;
}
/* calculate position for next char */
cx += WIDTH * base[0];
cy += WIDTH * base[1];
cz += WIDTH * base[2];
} // end for (i=0; i<len; i++)
if (plot_index <= 0) return null;
VisADLineArray array = new VisADLineArray();
float[] coordinates = new float[plot_index];
System.arraycopy(plot, 0, coordinates, 0, plot_index);
array.coordinates = coordinates;
array.vertexCount = plot_index / 3;
/* WLH 20 Feb 98
array.vertexFormat = COORDINATES;
*/
return array;
}
// number of significant digits after the decimal point
public static final int places = 3;
/** make a short string for value for use in slider label */
public static String shortString(double val)
{
// remember whether or not the number is negative
boolean negative = (val < 0.0);
double orig_val = val;
// now we only need to deal with a positive number
val = Math.abs(val);
if (val < 0.001) {
for (int i=1; i<30; i++) {
val *= 10.0;
orig_val *= 10.0;
if (val >= 0.1) {
return shortString(orig_val) + "E-" + i;
}
}
}
// build multiplier for saving significant digits
// also build value used to round up insignificant digits
int mult = 1;
float round = 0.5f;
for (int p = places; p > 0; p--) {
mult *= 10;
round /= 10;
}
// break into digits before (preDot) and after (postDot) the decimal point
long l = (long) ((val + round) * mult);
long preDot = l / mult;
int postDot = (int )(l % mult);
// format the pre-decimal point number
// Integer.toString() is faster than Long.toString(); use it if possible
String num;
if (preDot <= Integer.MAX_VALUE) {
num = Integer.toString((int )preDot);
} else {
num = Long.toString(preDot);
}
// if there's nothing after the decimal point, use the whole number
if (postDot == 0) {
// make sure we don't return "-0"
if (negative && preDot != 0) {
return "-" + num;
}
return num;
}
// start building the string
StringBuffer buf = new StringBuffer(num.length() + 5);
// add sign (if necessary), pre-decimal point digits and decimal point
if (negative) {
buf.append('-');
}
buf.append(num);
buf.append('.');
// format the post-decimal point digits
num = Integer.toString(postDot);
// add leading zeros if necessary
int nlen = num.length();
for (int p = places; p > nlen; p--) {
buf.append('0');
}
// add actual digits
buf.append(num);
// return the final string
return buf.toString();
}
}