NOTICE: This version of the NSF Unidata web site (archive.unidata.ucar.edu) is no longer being updated.
Current content can be found at unidata.ucar.edu.

To learn about what's going on, see About the Archive Site.

Re: Image plot colour scale

Hello Oliver,

at the risk of confusing you, I have simplified one of our classes
to provide you with a signal-strength scale (SignalStrengthScale.java)

I haven't tested the code (at least you don't have to worry about
compile-time errors), so I can't guarantee that it will work for you.

It assumes that your function type is:
(scanNumber, frequency) --> (signal-strength)

and the constructor takes a scalar map to each of these.

This was based on a rain-rate scale that we have written. We
can change the colour of the rain-rate via a LabeledColorWidget,
and when we do, the data as well as the rain-rate scale update.

Even if the code doesn't work for you, I hope you can get some
ideas from it.

Hope this helps,
Jim.
---
Jim Koutsovasilis
Bureau of Meteorology, Australia
jimk@xxxxxxxxxx



Oliver Mather wrote:

Hi there,
I have an image plot which shows the magnitude of the data using an RGB
map. http://mcba5.phys.unsw.edu.au:8180/~oliverm/ImagePlot.jpg

The user can modify the ranges of the plot scales, thus dynamically
changing the value each colour represents.
I?d like to add a colour scale next to the plot so that it always shows
the correct values the colous represents.This is because in most cases
the plot is saved as a GIF and printed for analysis later?
Is there a builtin feature of visad to do this ?


Thanks,
Oliver Mather
Software Engineer
Ph 04040 71153
omather@xxxxxxxxxx






// SignalStrengthScale.java

// Java
import java.awt.Component;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.geom.Point2D;
import java.rmi.RemoteException;
import java.util.Vector;
import java.util.prefs.Preferences;
import javax.swing.Icon;
import javax.swing.JComponent;

// VisAD
import visad.ColorAlphaControl;
import visad.ConstantMap;
import visad.DataReferenceImpl;
import visad.Display;
import visad.DisplayEvent;
import visad.DisplayImpl;
import visad.DisplayListener;
import visad.DisplayRenderer;
import visad.FieldImpl;
import visad.FunctionType;
import visad.Gridded2DDoubleSet;
import visad.Linear1DSet;
import visad.MouseBehavior;
import visad.Real;
import visad.RealType;
import visad.RealTupleType;
import visad.ScalarMap;
import visad.Set;
import visad.ShapeControl;
import visad.Text;
import visad.TextControl;
import visad.TextType;
import visad.VisADException;
import visad.VisADRay;
import visad.VisADGeometryArray;
import visad.VisADTriangleArray;
import visad.java3d.DefaultRendererJ3D;
import visad.java3d.DisplayRendererJ3D;
import visad.java3d.MouseBehaviorJ3D;
import visad.java3d.ProjectionControlJ3D;
import visad.util.ColorChangeEvent;
import visad.util.ColorChangeListener;
import visad.util.ColorMap;
import visad.util.LabeledColorWidget;


/**
 * Provides a signal strength scale for the function type:
 * (scan number, frequency)->(signal strength)
 *
 * The scale is drawn in the lower-left corner of the display.
 */
public final class SignalStrengthScale
{

        /**
         * The z value (height) of this layer.
         */
        private double zValue = -0.01;

        /**
         * The visad display we'll be adding this layer to.
         */
        private DisplayImpl display;

        /**
         * This data renderer for the scale.
         */
        private DefaultRendererJ3D scaleRenderer;

        /**
         * Maintains a reference to the visad data.
         */
        private DataReferenceImpl dataRef;

        /**
         * The frequency scalar map.
         */
        private ScalarMap frequencyMap;

        /**
         * The scan-number scalar map.
         */
        private ScalarMap scanNumberMap;

        /**
         * The signal-strength scalar map.
         */
        private ScalarMap signalStrengthMap;

        /**
         * The shape scalar map
         */
        private ScalarMap shapeMap;

        /**
         * The domain type (lat,lon)
         */
        private RealTupleType domainType;

        /**
         * The range type (shapeType)
         */
        private RealType shapeType;

        /**
         * If true, the first Display.TRANSFORM_DONE event has occurred.
         */
        private boolean firstTransformDone = false;

        /**
         * If true, the first Display.FRAME_DONE event has occurred.
         */
        private boolean firstFrameDone = false;

        /**
         * The width of the scale, as a percentage of the screen's width.
         */
        private float widthRatio = 0.35f;

        /**
         * The height of the scale, as a percentage of the screen's height.
         */
        private float heightRatio = 0.03f;

        /**
         * The offset from the screen corner for the signal-strength scale
         */
        private int offset = 10;

        /**
         * Holds the data coordinates (lat/lon) for the scale and its
         * labels.
         */
        private DataCoords dataCoords;

        /**
         * The font size to use for the scale's labels.
         */
        private int fontSize = 6;

        /**
         * The font to use for the scale's labels.
         */
        private String fontName = "Fast Font";

        /**
         * Holds data relating to the left-aligned labels.
         */
        private LabelType leftAlignedLabelType;

        /**
         * Holds data relating to the centred labels.
         */
        private LabelType centredLabelType;

        /**
         * Holds data relating to the right-aligned labels.
         */
        private LabelType rightAlignedLabelType;

        /**
         * Listens for changes to the Display.RGBA scalar map.
         */
        private ColourListener colourChangeListener;

        /**
         * This triangle array defines the signal-strength scale.
         */
        private VisADTriangleArray triangleArray;

        /**
         * Listens for changes to the visad window's size.
         */
        private CanvasResizeListener canvasResizeListener;

        /**
         * If true, the visad window has been resized.
         */
        private boolean resizedCanvas = false;

        /**
         * The number of canvas resize events we are going to process.
         */
        private int numCanvasResizeEvents = 0;


        /**
         * Constructor.
         *
         * @param display the visad display that this layer will be added to
         * @param frequencyMap the frequency scalar map
         * @param scanNumberMap the scan-number scalar map
         * @param signalStrenthMap the signal-strength scalar map
         *
         * @throws VisADException there's a problem with VisAD
         * @throws RemoteException there's a problem with VisAD
         */
        public SignalStrengthScale(final Display display,
                final ScalarMap scanNumberMap, final ScalarMap frequencyMap,
                final ScalarMap signalStrengthMap)
                throws VisADException, RemoteException
        {

                this.display = (DisplayImpl) display;
                this.frequencyMap = frequencyMap;
                this.scanNumberMap = scanNumberMap;
                this.signalStrengthMap = signalStrengthMap;

                domainType = RealTupleType.LatitudeLongitudeTuple;
                shapeType = RealType.getRealType("colour_shape");

                leftAlignedLabelType = LabelType.createLeftAligned();
                centredLabelType = LabelType.createCentred();
                rightAlignedLabelType = LabelType.createRightAligned();

                dataRef = new DataReferenceImpl("signalstrengthscale_data_ref");

                colourChangeListener = new ColourListener();
                LabeledColorWidget colourWidget = 
                        new LabeledColorWidget(signalStrengthMap);
                final ColorMap colourMap = colourWidget.getBaseMap();
                colourMap.addColorChangeListener(colourChangeListener);
                colourWidget = null;

                final DisplayRendererJ3D displayRenderer = (DisplayRendererJ3D) 
                        this.display.getDisplayRenderer();
                final Component canvas = displayRenderer.getCanvas();
                canvasResizeListener = new CanvasResizeListener();
                canvas.addComponentListener(canvasResizeListener);

        } // SignalStrengthScale.SignalStrengthScale()


        /**
         * Add scalar maps to the display
         *
         * @param display scalar maps are added to this display.
         *
         * @throws RemoteException there's a problem with VisAD
         * @throws VisADException there's a problem with VisAD
         */
        public void addScalarMaps(Display display)
                throws RemoteException, VisADException
        {

                shapeMap = new ScalarMap(shapeType, Display.Shape);
                display.addMap(shapeMap);

                display.addMap(leftAlignedLabelType.map);
                display.addMap(centredLabelType.map);
                display.addMap(rightAlignedLabelType.map);

                TextControl control = (TextControl) 
                        leftAlignedLabelType.map.getControl();
                control.setVerticalJustification(TextControl.Justification.TOP);
                control.setJustification(TextControl.Justification.LEFT);

                control = (TextControl) centredLabelType.map.getControl();
                control.setVerticalJustification(TextControl.Justification.TOP);
                control.setJustification(TextControl.Justification.CENTER);

                control = (TextControl) rightAlignedLabelType.map.getControl();
                control.setVerticalJustification(TextControl.Justification.TOP);
                control.setJustification(TextControl.Justification.RIGHT);

                ((DisplayImpl) display).addDisplayListener(
                        new DisplayChangedListener());

        } // SignalStrengthScale.addScalarMaps()


        /**
         * Add data references from the display.
         *
         * @param display data references are added to this display.
         *
         * @throws RemoteException there's a problem with VisAD
         * @throws VisADException there's a problem with VisAD
         */
        public void addDataReferences(Display display)
                throws RemoteException, VisADException
        {

                // Add the scale data reference to the display.
                ConstantMap [] maps = new ConstantMap [] {
                        new ConstantMap(zValue, Display.ZAxis)
                        };
                scaleRenderer = new DefaultRendererJ3D();
                display.addReferences(scaleRenderer, dataRef, maps);

                // Add the scale labels data reference to the display.
                maps = new ConstantMap [] {
                        new ConstantMap(zValue, Display.ZAxis),
                        new ConstantMap(0, Display.Red),
                        new ConstantMap(0, Display.Green),
                        new ConstantMap(0, Display.Blue),
                        };
                leftAlignedLabelType.renderer = 
                        new DefaultRendererJ3D();
                display.addReferences(leftAlignedLabelType.renderer,
                        leftAlignedLabelType.dataRef, maps);

                maps = new ConstantMap [] {
                        new ConstantMap(zValue, Display.ZAxis),
                        new ConstantMap(0, Display.Red),
                        new ConstantMap(0, Display.Green),
                        new ConstantMap(0, Display.Blue),
                        };
                centredLabelType.renderer = 
                        new DefaultRendererJ3D();
                display.addReferences(centredLabelType.renderer,
                        centredLabelType.dataRef, maps);

                maps = new ConstantMap [] {
                        new ConstantMap(zValue, Display.ZAxis),
                        new ConstantMap(0, Display.Red),
                        new ConstantMap(0, Display.Green),
                        new ConstantMap(0, Display.Blue),
                        };
                rightAlignedLabelType.renderer = 
                        new DefaultRendererJ3D();
                display.addReferences(rightAlignedLabelType.renderer,
                        rightAlignedLabelType.dataRef, maps);

        } // SignalStrengthScale.addDataReferences()


        /**
         * Retrieves the data values that correspond to the specified
         * screen location.
         *
         * @param mouseBehaviour the display renderer's mouse behavior
         * @param screenX the screen X coordinate
         * @param screenY the screen Y coordinate
         * @param latlon used to store the result; can be null.
         *
         * @return the data values that correspond to the specified
         *      screen location.
         */
         private Point2D.Double screenToDataCoords(
                final MouseBehavior mouseBehaviour, final int screenX, 
                final int screenY, Point2D.Double latLon)
        {
        
                final VisADRay ray = mouseBehaviour.findRay(screenX, screenY);
                final double [] cursor = new double[3]; 
                
                // X
                cursor[0] = ray.position[0];

                // Y
                cursor[1] = ray.position[1];

                // Z
                cursor[2] = ray.position[2];

                final double [] dummy1 = new double[2];
                final double [] dummy2 = new double[2];
                final double [] scaleOffset = new double[2];

                scanNumberMap.getScale(scaleOffset, dummy1, dummy2);
                final double lon = (cursor[0] - scaleOffset[1]) /
                        scaleOffset[0];

                frequencyMap.getScale(scaleOffset, dummy1, dummy2);
                final double lat = (cursor[1] - scaleOffset[1]) /
                        scaleOffset[0];

                if (null == latLon) {
                        latLon = new Point2D.Double();
                }

                latLon.x = lon;
                latLon.y = lat;

                return latLon;

        } // SignalStrengthScale.screenToDataCoords()


        /**
         * Creates a visad triangle array for the signal strength scale.
         *
         * @param height the height of the scale
         * @param width the width of the scale
         *
         * @return a visad triangle array that makes up the signal strength
         *      scale
         * @throws VisADException there's a problem with VisAD
         * @throws RemoteException there's a problem with VisAD
         */
        private VisADTriangleArray createTriangles(final float height, 
                final float width) throws VisADException, RemoteException
        {

                // Get the colour table used by the signalStrength scalar map.
                final ColorAlphaControl colourControl = 
                        (ColorAlphaControl) signalStrengthMap.getControl();
                final float [][] colourTable = colourControl.getTable();
                final int numColours = colourTable[0].length;

                final float delta = width / (float) numColours;
                final int numPointsPerTriangle = 3;
                final int numValuesPerPoint = 3;
                final int numTriangles = numColours * 2;
                final float [] triangles = new float[numTriangles *
                        numPointsPerTriangle * numValuesPerPoint];
                final byte [] colours = new byte[numTriangles *
                        numPointsPerTriangle * numValuesPerPoint];

                int index = 0;
                int colourIndex = 0;

                for (int i = 0; i < numColours; ++i) {

                        final byte red = (byte) (colourTable[0][i] * 255);
                        final byte green = (byte) (colourTable[1][i] * 255);
                        final byte blue = (byte) (colourTable[2][i] * 255);


                        // The right-half triangle
                        // 1     2
                        // .......
                        //  .    .
                        //   .   .
                        //    .  .
                        //     . .
                        //      ..
                        //       .
                        //       3

                        // First point in triangle
                        triangles[index++] = delta * i;
                        triangles[index++] = 0.0f;
                        triangles[index++] = 0.0f;

                        colours[colourIndex++] = red;
                        colours[colourIndex++] = green;
                        colours[colourIndex++] = blue; 

                        // Second point in triangle
                        triangles[index++] = (delta * i) + delta;
                        triangles[index++] = 0.0f;
                        triangles[index++] = 0.0f;

                        colours[colourIndex++] = red;
                        colours[colourIndex++] = green;
                        colours[colourIndex++] = blue;

                        // Third point in triangle
                        triangles[index++] = (delta * i) + delta;
                        triangles[index++] = height;
                        triangles[index++] = 0.0f;

                        colours[colourIndex++] = red;
                        colours[colourIndex++] = green;
                        colours[colourIndex++] = blue;


                        // The left-half triangle
                        // 1
                        // .
                        // ..
                        // . .
                        // .  .
                        // .   .
                        // .    .
                        // .......
                        // 3     2

                        // First point in triangle
                        triangles[index++] = delta * i;
                        triangles[index++] = 0.0f;
                        triangles[index++] = 0.0f;

                        colours[colourIndex++] = red;
                        colours[colourIndex++] = green;
                        colours[colourIndex++] = blue;

                        // Second point in triangle
                        triangles[index++] = (delta * i) + delta;
                        triangles[index++] = height;
                        triangles[index++] = 0.0f;

                        colours[colourIndex++] = red;
                        colours[colourIndex++] = green;
                        colours[colourIndex++] = blue; 

                        // Third point in triangle
                        triangles[index++] = delta * i;
                        triangles[index++] = height;
                        triangles[index++] = 0.0f;

                        colours[colourIndex++] = red;
                        colours[colourIndex++] = green;
                        colours[colourIndex++] = blue;

                } // for (i<numColours)


                // Set all the normal vectors to (0,0,1) for each
                // vertex of each triangle.

                final float [] normals = new float[numTriangles *
                        numPointsPerTriangle * numValuesPerPoint];

                index = 0;
                for (int i = 0; i < numTriangles; ++i) {

                        // First point in triangle.
                        normals[index++] = 0.0f;
                        normals[index++] = 0.0f;
                        normals[index++] = 1.0f;

                        // Second point in triangle.
                        normals[index++] = 0.0f;
                        normals[index++] = 0.0f;
                        normals[index++] = 1.0f;

                        // Third point in triangle.
                        normals[index++] = 0.0f;
                        normals[index++] = 0.0f;
                        normals[index++] = 1.0f;

                } // for (i<numTriangles)

                final VisADTriangleArray triangleArray
                        new VisADTriangleArray();
                triangleArray.coordinates = triangles;
                triangleArray.normals = normals;
                triangleArray.colors = colours;
                triangleArray.vertexCount = numTriangles * numPointsPerTriangle;

                return triangleArray;

        } // SignalStrengthScale.createTriangles()

        
        /**
         * Allows us to listen to Display events.
         */
        private class DisplayChangedListener implements DisplayListener
        {

                /**
                 * A display changed event has occurred, so determine
                 * if we can draw the scale.
                 *
                 * @param event contains information about this event
                 *
                 * @throws VisADException there's a problem with VisAD
                 * @throws RemoteException there's a problem with VisAD
                 */
                public void displayChanged(DisplayEvent event)
                        throws VisADException, RemoteException
                {

                        switch (event.getId()) {

                        case DisplayEvent.FRAME_DONE:
                                if (!firstTransformDone) {
                                        return;
                                }

                                if (!firstFrameDone) {
                                        redraw();
                                        firstFrameDone = true;
                                        return;
                                }

                                if (resizedCanvas) {

                                        // The canvas has been resized
                                        // and there are more events to
                                        // process.
                                        --numCanvasResizeEvents;
                                        if (0 == numCanvasResizeEvents) {
                                                resizedCanvas = false;
                                        }
                                        redraw();

                                } // if (resizedCanvas)

                                break;

                        case DisplayEvent.TRANSFORM_DONE:
                                firstTransformDone = true;
                                break;

                        case DisplayEvent.MOUSE_RELEASED_LEFT:
                                // The user has zoomed or panned, so
                                // redraw the scale.
                                redraw();
                                break;

                        } // switch()

                } // DisplayChangedListener.displayChanged()

        } // class SignalStrengthScale.DisplayChangedListener


        /**
         * Creates the visad field and all the data that is used
         * by the signal strength scale.
         *
         * @return a visad field that contains all the scale data
         *
         * @throws VisADException there's a problem with VisAD
         * @throws RemoteException there's a problem with VisAD
         */
        private FieldImpl createField() throws VisADException, RemoteException
        {

                final double deltaLat = Math.abs(
                        dataCoords.bottomRightOfScale.y -
                        dataCoords.topLeftOfScale.y);
                final double deltaLon = Math.abs(
                        dataCoords.bottomRightOfScale.x -
                        dataCoords.topLeftOfScale.x);

                // This scale was found experimentally, and it seems
                // to work well for all occassions.
                final float scale = 0.0055f;

                /*
                final VisADTriangleArray triangleArray
                        createTriangles((float) deltaLat * scale, 
                                (float) deltaLon * scale);
                */
                triangleArray = createTriangles((float) deltaLat * scale, 
                                (float) deltaLon * scale);

                // Setup the shape control with the new triangle array shape.
                final ShapeControl shapeControl = 
                        (ShapeControl) shapeMap.getControl();
                shapeControl.setShapeSet(new Linear1DSet(0, 1, 1));
                final VisADGeometryArray [] shapes = new VisADGeometryArray[] {
                        triangleArray };
                shapeControl.setShapes(shapes);

                // Place the shape at the lower left corner of the screen.
                final double [][] domainSamples = new double[2][1];
                domainSamples[0][0] = dataCoords.bottomRightOfScale.y;
                domainSamples[1][0] = dataCoords.topLeftOfScale.x;
                final Set domainSet = new Gridded2DDoubleSet(domainType,
                        domainSamples, 1);

                final FunctionType functionType = new FunctionType(
                        domainType, shapeType);
                final FieldImpl field = new FieldImpl(functionType, domainSet);
                field.setSample(0, new Real(shapeType, 0));

                return field;

        } // SignalStrengthScale.createField()


        /**
         * Creates the field and data for the scale labels.
         *
         * @throws VisADException there's a problem in VisAD
         * @throws RemoteException there's a problem in VisAD
         */
        private void setupLabelData()
                throws VisADException, RemoteException
        {

                double [][] domainSamples = new double[2][1];
                domainSamples[0][0] = dataCoords.leftLabel.y;
                domainSamples[1][0] = dataCoords.leftLabel.x;
                Gridded2DDoubleSet domainSet = new Gridded2DDoubleSet(
                        domainType, domainSamples, 1);
                FunctionType functionType = new FunctionType(domainType,
                        leftAlignedLabelType.type);
                FieldImpl field = new FieldImpl(functionType, domainSet);
                field.setSample(0, new Text(leftAlignedLabelType.type,
                        "Light"));
                leftAlignedLabelType.dataRef.setData(field);

                domainSamples[0][0] = dataCoords.centreLabel.y;
                domainSamples[1][0] = dataCoords.centreLabel.x;
                domainSet = new Gridded2DDoubleSet(domainType,
                        domainSamples, 1);
                functionType = new FunctionType(domainType,
                        centredLabelType.type);
                field = new FieldImpl(functionType, domainSet);
                field.setSample(0, new Text(centredLabelType.type,
                        "Moderate"));
                centredLabelType.dataRef.setData(field);

                domainSamples[0][0] = dataCoords.rightLabel.y;
                domainSamples[1][0] = dataCoords.rightLabel.x;
                domainSet = new Gridded2DDoubleSet(domainType,
                        domainSamples, 1);
                functionType = new FunctionType(domainType,
                        rightAlignedLabelType.type);
                field = new FieldImpl(functionType, domainSet);
                field.setSample(0, new Text(rightAlignedLabelType.type,
                        "Heavy"));
                rightAlignedLabelType.dataRef.setData(field);

                formatLabels();

        } // SignalStrengthScale.setupLabelData()


        /**
         * Setup the data coordinates for the scale and its labels.
         */
        private DataCoords setupDataCoords()
        {

                // ........................................ 
                // .                                      .
                // ........................................ 
                // |                  |                   |
                // Light           Moderate           Heavy
                //
                // 
                final Rectangle screenRect = display.getComponent().getBounds();
                final int labelOffset = 5;

                final int scaleWidth = (int) (screenRect.width * widthRatio);
                final int scaleHeight = (int) (screenRect.height * heightRatio);

                final int left = offset;
                final int right = left + scaleWidth;

                final int labelTop = screenRect.height - offset -
                        (2 * fontSize); 
                final int labelCentre = left + ((right - left) / 2);
                final int labelLeft = left;
                final int labelRight = right;

                final int bottom = labelTop - labelOffset;
                final int top = bottom - scaleHeight;

                final DisplayRenderer displayRenderer = 
                        display.getDisplayRenderer();
                final MouseBehavior mouseBehaviour = 
                        displayRenderer.getMouseBehavior();
                final Point2D.Double topLeft = screenToDataCoords(
                        mouseBehaviour, 
                        left, top, null);
                final Point2D.Double bottomRight = screenToDataCoords(
                        mouseBehaviour, right, bottom, null);

                final DataCoords coordinates = new DataCoords();

                coordinates.topLeftOfScale = screenToDataCoords(mouseBehaviour,
                        left, top, null);
                coordinates.bottomRightOfScale = screenToDataCoords(
                        mouseBehaviour, right, bottom, null);
                        
                coordinates.leftLabel = screenToDataCoords(mouseBehaviour,
                        labelLeft, labelTop, null);
                coordinates.centreLabel = screenToDataCoords(mouseBehaviour,
                        labelCentre, labelTop, null);
                coordinates.rightLabel = screenToDataCoords(mouseBehaviour,
                        labelRight, labelTop, null);

                return coordinates;

        } // SignalStrengthScale.setupDataCoords()


        /**
         * Wraps up the data coordinates (lat,lon) of the scale
         * and its labels.
         */
        private static class DataCoords
        {

                /**
                 * The top left corner of the scale.
                 */
                private Point2D.Double topLeftOfScale;

                /**
                 * The bottom right corner of the scale.
                 */
                private Point2D.Double bottomRightOfScale;

                /**
                 * The coordinate of the "Light" label. 
                 */
                private Point2D.Double leftLabel;

                /**
                 * The corrdinate of the "Moderate" label.
                 */
                private Point2D.Double centreLabel;

                /**
                 * The coordinate of the "Heavy" label.
                 */
                private Point2D.Double rightLabel;

        } // class SignalStrengthScale.DataCoords


        /**
         * Formats the labels so they are centred, top justified, and
         * have a small font size.
         *
         * @throws VisADException there's a problem with VisAD
         * @throws RemoteException there's a problem with VisAD
         */
        private void formatLabels() throws VisADException, RemoteException
        {


                // To set the correct font size, we have to undo
                // the current level of zoom, and then set our
                // font size.
                final ProjectionControlJ3D projectionControl = 
                        (ProjectionControlJ3D)
                        this.display.getProjectionControl();
                final double [] scale = new double[1];
                final double [] translation = new double[3];
                final double [] rotation = new double[3];
                MouseBehaviorJ3D.unmake_matrix(rotation, scale,
                        translation, projectionControl.getMatrix());

                final double baseFontSize = 14;
                Font font = null;
                if (!fontName.equals("Fast Font")) {
                        font = new Font(fontName, Font.PLAIN, fontSize);
                }

                TextControl textControl = (TextControl)
                        leftAlignedLabelType.map.getControl();
                textControl.setSize((fontSize / baseFontSize) / scale[0]);
                textControl.setFont(font);

                textControl = (TextControl)
                        centredLabelType.map.getControl();
                textControl.setSize((fontSize / baseFontSize) / scale[0]);
                textControl.setFont(font);

                textControl = (TextControl)
                        rightAlignedLabelType.map.getControl();
                textControl.setSize((fontSize / baseFontSize) / scale[0]);
                textControl.setFont(font);

        } // SignalStrengthScale.formatLabels()


        /**
         * Wraps up data for a particularly-aligned Text control.
         */
        private static class LabelType 
        {

                /**
                 * Creates a left-aligned label type.
                 *
                 * @throws VisAException there's a problem with VisAD
                 */
                public static LabelType createLeftAligned()
                        throws VisADException
                {
                        
                        return new LabelType(TextControl.Justification.LEFT);

                } // LabelType.createLeftAligned()


                /**
                 * Creates a centred label type.
                 *
                 * @throws VisAException there's a problem with VisAD
                 */
                public static LabelType createCentred()
                        throws VisADException
                {

                        return new LabelType(TextControl.Justification.CENTER);

                } // LabelType.createCentred()


                /**
                 * Creates a right-aligned label type.
                 *
                 * @throws VisAException there's a problem with VisAD
                 */
                public static LabelType createRightAligned()
                        throws VisADException
                {

                        return new LabelType(TextControl.Justification.RIGHT);

                } // LabelType.createRightAligned()


                /**
                 * Private constructor means only factory methods can
                 * create an instance of this class.
                 *
                 * @param justification the horizontal justification for
                 *      this label.
                 * @throws VisADException there's a problem with VisAD
                 */
                private LabelType(TextControl.Justification justification)
                        throws VisADException
                {

                        String name = null;

                        if (TextControl.Justification.LEFT == justification) {
                                name = "left-aligned";
                        } else if (TextControl.Justification.CENTER =
                                justification)
                        {
                                name = "centred";
                        } else if (TextControl.Justification.RIGHT =
                                justification)
                        {
                                name = "right-aligned";
                        } else {
                                throw new IllegalArgumentException(
                                        "Bad type of horizontal justification");
                        }

                        type = TextType.getTextType(name);
                        map = new ScalarMap(type, Display.Text);
                        dataRef = new DataReferenceImpl(name);

                } // LabelTypel.LabelType()


                /**
                 * The text type for this type of label. 
                 */
                private TextType type;

                /**
                 * The scalar map that maps "type" to Display.Text
                 */
                private ScalarMap map;

                /**
                 * The data reference.
                 */
                private DataReferenceImpl dataRef;

                /**
                 * The label's renderer.
                 */
                private DefaultRendererJ3D renderer;

        } // class SignalStrengthScale.LabelType


        /**
         * Listens for colour changes in the scalar map:
         * RealType.signalStrength --> Display.RGBA
         */
        private class ColourListener implements ColorChangeListener
        {

                /**
                 * The colour table has changed, so update the signal-strength
                 * scale.
                 */
                public synchronized void colorChanged(ColorChangeEvent event)
                {
                
                        if (firstFrameDone) {

                                Exception exception = null;

                                try {
                                        redraw();
                                } catch (VisADException ex) {
                                        exception = ex;
                                } catch (RemoteException ex) {
                                        exception = ex;
                                }

                                if (exception != null) {
                                        System.err.println(
                                                "SignalStrengthScale." +
                                                "ColourListener.colorChanged:" +
                                                " could not update colours");
                                }

                        } // if (firstFrameDone)

                } // ColourListener.colorChanged()

        } // class SignalStrengthScale.ColourListener

        
        /**
         * When the visad window is resized, we need to redraw the
         * signal-strength scale.
         */
        private class CanvasResizeListener extends ComponentAdapter
        {
        
                /**
                 * The visad window has been resized, so redraw.
                 */
                public synchronized void componentResized(ComponentEvent event)
                {
                        
                        if (!firstFrameDone) {
                                // We're not ready to handle resize events
                                // just yet.
                                return;
                        }

                        // We'll process the first two FRAME_DONE events
                        numCanvasResizeEvents = 2;
                        resizedCanvas = true;

                } // CanvasResizeListener.componentResized()

        } // class SignalStrengthScale.CanvasResizeListener

        
        /**
         * Redraws the signal-strength scale and the labels.
         *
         * @throws VisADException there's a problem in VisAD
         * @throws RemoteException there's a problem in VisAD
         */
        private synchronized void redraw()
                throws VisADException, RemoteException
        {

                dataCoords = setupDataCoords();
                dataRef.setData(createField());
                setupLabelData();

        } // SignalStrengthScale.redraw()

} // class SignalStrengthScale
  • 2003 messages navigation, sorted by:
    1. Thread
    2. Subject
    3. Author
    4. Date
    5. ↑ Table Of Contents
  • Search the visad archives: