//
// HSVDisplay.java
//
/*
VisAD system for interactive analysis and visualization of numerical
data. Copyright (C) 1996 - 2017 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
*/
import visad.*;
import visad.java3d.*;
import visad.util.*;
import java.io.IOException;
import java.rmi.RemoteException;
// JFC packages
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.border.*;
// AWT packages
import java.awt.*;
import java.awt.event.*;
/**
HSVDisplay is an application for interactively exploring
the relation between the HSV and RGB color coordiantes.<P>
*/
public class HSVDisplay extends Object implements ActionListener {
DisplayImplJ3D display1 = null;
RealType red = null;
RealType green = null;
RealType blue = null;
RealType hue = null;
RealType saturation = null;
RealType value = null;
ContourCell cell_hue = null;
ContourCell cell_saturation = null;
ContourCell cell_value = null;
ContourControl controlhcontour = null;
ContourControl controlscontour = null;
ContourControl controlvcontour = null;
int state = 0; // number of ScalarMaps added, 0 through 9
ScalarMap[] maps = new ScalarMap[9];
public static void main(String args[])
throws IOException, VisADException, RemoteException {
HSVDisplay dummy = new HSVDisplay();
}
public HSVDisplay()
throws IOException, VisADException, RemoteException {
// define an rgb color space
// (not to be confused with system's RGB DisplayTupleType)
red = RealType.getRealType("red");
green = RealType.getRealType("green");
blue = RealType.getRealType("blue");
RealTupleType rgb = new RealTupleType(red, green, blue);
// define an hsv color space
// (not to be confused with system's HSV DisplayTupleType)
hue = RealType.getRealType("hue", CommonUnit.degree);
saturation = RealType.getRealType("saturation");
value = RealType.getRealType("value");
// note that we use the same HSVCoordinateSystem that the
// system uses to define the relation between its RGB and HSV
CoordinateSystem hsv_system = new HSVCoordinateSystem(rgb);
RealTupleType hsv = new RealTupleType(hue, saturation, value,
hsv_system, null);
// construct a sampling of the hsv color space;
// since hue is composed of six linear (in rgb) pieces with
// discontinuous derivative bwteen pieces, it should be sampled
// at 6*n+1 points with n not too small;
// for a given hue, saturation and value are both linear in rgb
// so 2 samples suffice for each of them;
// the HSV - RGB transform is degenerate at saturation = 0.0
// and value = 0.0 so avoid those values;
// hue is in Units of degrees so that must be used in the Set
// constructor
Linear3DSet cube_set =
new Linear3DSet(hsv, 0.0, 360.0, 37,
0.01, 1.0, 2,
0.01, 1.0, 2, null,
new Unit[] {CommonUnit.degree, null, null},
null);
// construct a DataReference to cube_set so it can be displayed
DataReference cube_ref = new DataReferenceImpl("cube");
cube_ref.setData(cube_set);
DataReference hue_ref =
new DataReferenceImpl("hue");
DataReference saturation_ref =
new DataReferenceImpl("saturation");
DataReference value_ref =
new DataReferenceImpl("value");
VisADSlider hue_slider =
new VisADSlider("hue", 0, 359, 0, 1.0, hue_ref,
RealType.Generic);
VisADSlider saturation_slider =
new VisADSlider("saturation", 0, 100, 0, 0.01, saturation_ref,
RealType.Generic);
VisADSlider value_slider =
new VisADSlider("value", 0, 100, 0, 0.01, value_ref,
RealType.Generic);
// construct a Display
display1 = new DisplayImplJ3D("display1");
// makeMaps();
// makeColorMaps();
for (int i=0; i<9; i++) addMap();
display1.getGraphicsModeControl().setScaleEnable(true);
DisplayRendererJ3D dr = (DisplayRendererJ3D) display1.getDisplayRenderer();
KeyboardBehaviorJ3D kbd = new KeyboardBehaviorJ3D(dr);
dr.addKeyboardBehavior(kbd);
// display cube_set
display1.addReference(cube_ref);
JFrame frame = new JFrame("VisAD HSV Color Coordinates");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
// create JPanel in frame
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setAlignmentY(JPanel.TOP_ALIGNMENT);
panel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
frame.getContentPane().add(panel);
panel.add(hue_slider);
panel.add(saturation_slider);
panel.add(value_slider);
panel.add(display1.getComponent());
JPanel panel2 = new JPanel();
panel2.setLayout(new BoxLayout(panel2, BoxLayout.X_AXIS));
panel2.setAlignmentY(JPanel.TOP_ALIGNMENT);
panel2.setAlignmentX(JPanel.LEFT_ALIGNMENT);
JButton clear = new JButton("Clear");
clear.addActionListener(this);
clear.setActionCommand("clear");
panel2.add(clear);
JButton add = new JButton("Add");
add.addActionListener(this);
add.setActionCommand("add");
panel2.add(add);
JButton remove = new JButton("Remove");
remove.addActionListener(this);
remove.setActionCommand("remove");
panel2.add(remove);
panel.add(panel2);
int WIDTH = 500;
int HEIGHT = 700;
frame.setSize(WIDTH, HEIGHT);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(screenSize.width/2 - WIDTH/2,
screenSize.height/2 - HEIGHT/2);
frame.setVisible(true);
cell_hue =
new ContourCell(controlhcontour, hue_ref);
cell_hue.addReference(hue_ref);
cell_saturation =
new ContourCell(controlscontour, saturation_ref);
cell_saturation.addReference(saturation_ref);
cell_value =
new ContourCell(controlvcontour, value_ref);
cell_value.addReference(value_ref);
}
/** This method handles button presses */
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
try {
if (cmd.equals("clear")) {
display1.clearMaps();
controlhcontour = null;
controlscontour = null;
controlvcontour = null;
setControls();
for (int i=0; i<9; i++) maps[i] = null;
state = 0;
}
else if (cmd.equals("add")) {
addMap();
}
else if (cmd.equals("remove")) {
removeMap();
}
}
catch (VisADException ex) {
System.out.println("call clearMaps ex = " + ex);
}
catch (RemoteException ex) {
System.out.println("call clearMaps ex = " + ex);
}
}
private void addMap()
throws VisADException, RemoteException {
switch (state) {
case 0:
maps[0] = new ScalarMap(red, Display.XAxis);
display1.addMap(maps[0]);
break;
case 1:
maps[1] = new ScalarMap(green, Display.YAxis);
display1.addMap(maps[1]);
break;
case 2:
maps[2] = new ScalarMap(blue, Display.ZAxis);
display1.addMap(maps[2]);
break;
case 3:
maps[3] = new ScalarMap(hue, Display.IsoContour);
display1.addMap(maps[3]);
controlhcontour = (ContourControl) maps[3].getControl();
if (cell_hue != null) cell_hue.setControl(controlhcontour);
break;
case 4:
maps[4] = new ScalarMap(saturation, Display.IsoContour);
display1.addMap(maps[4]);
controlscontour = (ContourControl) maps[4].getControl();
if (cell_saturation != null) cell_saturation.setControl(controlscontour);
break;
case 5:
maps[5] = new ScalarMap(value, Display.IsoContour);
display1.addMap(maps[5]);
controlvcontour = (ContourControl) maps[5].getControl();
if (cell_value != null) cell_value.setControl(controlvcontour);
break;
case 6:
maps[6] = new ScalarMap(hue, Display.Hue);
display1.addMap(maps[6]);
break;
case 7:
maps[7] = new ScalarMap(saturation, Display.Saturation);
display1.addMap(maps[7]);
break;
case 8:
maps[8] = new ScalarMap(value, Display.Value);
display1.addMap(maps[8]);
break;
case 9:
return;
}
state++;
}
private void removeMap()
throws VisADException, RemoteException {
switch (state) {
case 0:
return;
case 4:
controlhcontour = null;
if (cell_hue != null) cell_hue.setControl(controlhcontour);
break;
case 5:
controlscontour = null;
if (cell_saturation != null) cell_saturation.setControl(controlscontour);
break;
case 6:
controlvcontour = null;
if (cell_value != null) cell_value.setControl(controlvcontour);
break;
default:
break;
}
state--;
display1.removeMap(maps[state]);
maps[state] = null;
}
private void setControls()
throws VisADException, RemoteException {
cell_hue.setControl(controlhcontour);
cell_saturation.setControl(controlscontour);
cell_value.setControl(controlvcontour);
}
class ContourCell extends CellImpl {
ContourControl control;
DataReference ref;
double value;
ContourCell(ContourControl cc, DataReference r)
throws VisADException, RemoteException {
control = cc;
ref = r;
value = ((Real) ref.getData()).getValue();
}
public void setControl(ContourControl cc)
throws VisADException, RemoteException {
control = cc;
value = Double.NaN;
doAction();
}
public void doAction() throws VisADException, RemoteException {
double val = ((Real) ref.getData()).getValue();
ContourControl cc = control;
if (val == val && val != value && cc != null) {
cc.setSurfaceValue((float) ((Real) ref.getData()).getValue());
cc.enableContours(true);
value = val;
}
}
}
}