//
// RubberBandBoxRendererJ3D.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
*/
package visad.bom;
import visad.*;
import visad.java3d.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Vector;
import java.util.Enumeration;
import java.rmi.*;
import javax.media.j3d.*;
/**
RubberBandBoxRendererJ3D is the VisAD class for direct
manipulation of rubber band boxes
*/
public class RubberBandBoxRendererJ3D extends DirectManipulationRendererJ3D {
private RealType x = null;
private RealType y = null;
private RealTupleType xy = null;
private int mouseModifiersMask = 0;
private int mouseModifiersValue = 0;
private BranchGroup branch = null;
private BranchGroup group = null;
/** this DirectManipulationRenderer is quite different - it does not
render its data, but only place values into its DataReference
on right mouse button release;
it uses xarg and yarg to determine spatial ScalarMaps */
public RubberBandBoxRendererJ3D (RealType xarg, RealType yarg) {
this(xarg, yarg, 0, 0);
}
/** xarg and yarg determine spatial ScalarMaps;
mmm and mmv determine whehter SHIFT or CTRL keys are required -
this is needed since this is a greedy DirectManipulationRenderer
that will grab any right mouse click (that intersects its 2-D
sub-manifold) */
public RubberBandBoxRendererJ3D (RealType xarg, RealType yarg, int mmm, int mmv) {
super();
x = xarg;
y = yarg;
mouseModifiersMask = mmm;
mouseModifiersValue = mmv;
}
/** don't render - just return BranchGroup for scene graph to
render rectangle into */
public synchronized BranchGroup doTransform()
throws VisADException, RemoteException {
branch = new BranchGroup();
branch.setCapability(BranchGroup.ALLOW_DETACH);
branch.setCapability(Group.ALLOW_CHILDREN_READ);
branch.setCapability(Group.ALLOW_CHILDREN_WRITE);
branch.setCapability(Group.ALLOW_CHILDREN_EXTEND);
// check type and maps for valid direct manipulation
if (!getIsDirectManipulation()) {
throw new BadDirectManipulationException(getWhyNotDirect() +
": DirectManipulationRendererJ3D.doTransform");
}
setBranch(branch);
return branch;
}
/** for use in drag_direct */
private transient DataDisplayLink link = null;
private transient DataReference ref = null;
private transient ScalarMap xmap = null;
private transient ScalarMap ymap = null;
float[] default_values;
/** arrays of length one for inverseScaleValues */
private float[] f = new float[1];
private float[] d = new float[1];
private float[] value = new float[2];
/** information calculated by checkDirect */
/** explanation for invalid use of DirectManipulationRenderer */
private String whyNotDirect = null;
/** dimension of direct manipulation
(always 2 for RubberBandBoxRendererJ3D) */
private int directManifoldDimension = 2;
/** spatial DisplayTupleType other than
DisplaySpatialCartesianTuple */
private DisplayTupleType tuple;
private CoordinateSystem tuplecs;
private int xindex = -1;
private int yindex = -1;
private int otherindex = -1;
private float othervalue;
private byte red, green, blue; // default colors
private float[][] first_x;
private float[][] last_x;
private float[][] clast_x;
private float cum_lon;
/** possible values for whyNotDirect */
private final static String xandyNotMatch =
"x and y spatial domains don't match";
private final static String xandyNotSpatial =
"x and y must be mapped to spatial";
private boolean stop = false;
public void checkDirect() throws VisADException, RemoteException {
setIsDirectManipulation(false);
DisplayImpl display = getDisplay();
DataDisplayLink[] Links = getLinks();
if (Links == null || Links.length == 0) {
link = null;
return;
}
link = Links[0];
ref = link.getDataReference();
default_values = link.getDefaultValues();
xmap = null;
ymap = null;
Vector scalar_map_vector = display.getMapVector();
Enumeration en = scalar_map_vector.elements();
while (en.hasMoreElements()) {
ScalarMap map = (ScalarMap) en.nextElement();
ScalarType real = map.getScalar();
if (real.equals(x)) {
DisplayRealType dreal = map.getDisplayScalar();
DisplayTupleType t = dreal.getTuple();
if (t != null &&
(t.equals(Display.DisplaySpatialCartesianTuple) ||
(t.getCoordinateSystem() != null &&
t.getCoordinateSystem().getReference().equals(
Display.DisplaySpatialCartesianTuple)))) {
xmap = map;
xindex = dreal.getTupleIndex();
if (tuple == null) {
tuple = t;
}
else if (!t.equals(tuple)) {
whyNotDirect = xandyNotMatch;
return;
}
}
}
if (real.equals(y)) {
DisplayRealType dreal = map.getDisplayScalar();
DisplayTupleType t = dreal.getTuple();
if (t != null &&
(t.equals(Display.DisplaySpatialCartesianTuple) ||
(t.getCoordinateSystem() != null &&
t.getCoordinateSystem().getReference().equals(
Display.DisplaySpatialCartesianTuple)))) {
ymap = map;
yindex = dreal.getTupleIndex();
if (tuple == null) {
tuple = t;
}
else if (!t.equals(tuple)) {
whyNotDirect = xandyNotMatch;
return;
}
}
}
}
if (xmap == null || ymap == null) {
whyNotDirect = xandyNotSpatial;
return;
}
xy = new RealTupleType(x, y);
// get default value for other component of tuple
otherindex = 3 - (xindex + yindex);
DisplayRealType dreal = (DisplayRealType) tuple.getComponent(otherindex);
int index = getDisplay().getDisplayScalarIndex(dreal);
othervalue = (index > 0) ? default_values[index] :
(float) dreal.getDefaultValue();
// get default colors
index = getDisplay().getDisplayScalarIndex(Display.Red);
float v = (index > 0) ? default_values[index] :
(float) Display.Red.getDefaultValue();
red = ShadowType.floatToByte(v);
index = getDisplay().getDisplayScalarIndex(Display.Green);
v = (index > 0) ? default_values[index] :
(float) Display.Green.getDefaultValue();
green = ShadowType.floatToByte(v);
index = getDisplay().getDisplayScalarIndex(Display.Blue);
v = (index > 0) ? default_values[index] :
(float) Display.Blue.getDefaultValue();
blue = ShadowType.floatToByte(v);
if (Display.DisplaySpatialCartesianTuple.equals(tuple)) {
tuple = null;
tuplecs = null;
}
else {
tuplecs = tuple.getCoordinateSystem();
}
directManifoldDimension = 2;
setIsDirectManipulation(true);
}
private int getDirectManifoldDimension() {
return directManifoldDimension;
}
public String getWhyNotDirect() {
return whyNotDirect;
}
public void addPoint(float[] x) throws VisADException {
// may need to do this for performance
}
// methods customized from DataRenderer:
public CoordinateSystem getDisplayCoordinateSystem() {
return tuplecs;
}
/** set spatialValues from ShadowType.doTransform */
public synchronized void setSpatialValues(float[][] spatial_values) {
// do nothing
}
/** check if ray intersects sub-manifold */
public synchronized float checkClose(double[] origin, double[] direction) {
int mouseModifiers = getLastMouseModifiers();
if ((mouseModifiers & mouseModifiersMask) != mouseModifiersValue) {
return Float.MAX_VALUE;
}
try {
float r = findRayManifoldIntersection(true, origin, direction, tuple,
otherindex, othervalue);
if (r == r) {
return 0.0f;
}
else {
return Float.MAX_VALUE;
}
}
catch (VisADException ex) {
return Float.MAX_VALUE;
}
}
/** mouse button released, ending direct manipulation */
public synchronized void release_direct() {
// set data in ref
if (group != null) group.detach();
group = null;
try {
float[][] samples = new float[2][2];
f[0] = first_x[xindex][0];
d = xmap.inverseScaleValues(f);
samples[0][0] = (float) d[0];
f[0] = first_x[yindex][0];
d = ymap.inverseScaleValues(f);
samples[1][0] = (float) d[0];
f[0] = last_x[xindex][0];
d = xmap.inverseScaleValues(f);
samples[0][1] = (float) d[0];
f[0] = last_x[yindex][0];
d = ymap.inverseScaleValues(f);
samples[1][1] = (float) d[0];
Gridded2DSet set = new Gridded2DSet(xy, samples, 2);
ref.setData(set);
link.clearData();
} // end try
catch (VisADException e) {
// do nothing
System.out.println("release_direct " + e);
e.printStackTrace();
}
catch (RemoteException e) {
// do nothing
System.out.println("release_direct " + e);
e.printStackTrace();
}
}
public void stop_direct() {
stop = true;
}
private static final int EDGE = 20;
private static final float EPS = 0.005f;
public synchronized void drag_direct(VisADRay ray, boolean first,
int mouseModifiers) {
if (ref == null) return;
if (first) {
stop = false;
}
else {
if (stop) return;
}
double[] origin = ray.position;
double[] direction = ray.vector;
try {
float r = findRayManifoldIntersection(true, origin, direction, tuple,
otherindex, othervalue);
if (r != r) {
if (group != null) group.detach();
return;
}
float[][] xx = {{(float) (origin[0] + r * direction[0])},
{(float) (origin[1] + r * direction[1])},
{(float) (origin[2] + r * direction[2])}};
if (tuple != null) xx = tuplecs.fromReference(xx);
if (first) {
first_x = xx;
cum_lon = 0.0f;
}
else if (Display.DisplaySpatialSphericalTuple.equals(tuple)) {
float diff = xx[1][0] - clast_x[1][0];
if (diff > 180.0f) diff -= 360.0f;
else if (diff < -180.0f) diff += 360.0f;
cum_lon += diff;
if (cum_lon > 360.0f) cum_lon -= 360.0f;
else if (cum_lon < -360.0f) cum_lon += 360.0f;
}
clast_x = xx;
Vector vect = new Vector();
f[0] = xx[xindex][0];
d = xmap.inverseScaleValues(f);
// WLH 31 Aug 2000
Real rr = new Real(x, d[0]);
Unit overrideUnit = xmap.getOverrideUnit();
Unit rtunit = x.getDefaultUnit();
// units not part of Time string
if (overrideUnit != null && !overrideUnit.equals(rtunit) &&
!RealType.Time.equals(x)) {
double dval = overrideUnit.toThis((double) d[0], rtunit);
rr = new Real(x, dval, overrideUnit);
}
String valueString = rr.toValueString();
vect.addElement(x.getName() + " = " + valueString);
f[0] = xx[yindex][0];
d = ymap.inverseScaleValues(f);
// WLH 31 Aug 2000
rr = new Real(y, d[0]);
overrideUnit = ymap.getOverrideUnit();
rtunit = y.getDefaultUnit();
// units not part of Time string
if (overrideUnit != null && !overrideUnit.equals(rtunit) &&
!RealType.Time.equals(y)) {
double dval = overrideUnit.toThis((double) d[0], rtunit);
rr = new Real(y, dval, overrideUnit);
}
valueString = rr.toValueString();
valueString = new Real(y, d[0]).toValueString();
vect.addElement(y.getName() + " = " + valueString);
getDisplayRenderer().setCursorStringVector(vect);
float[][] xxp = {{xx[0][0]}, {xx[1][0]}, {xx[2][0]}};
xxp[otherindex][0] += EPS;
if (tuplecs != null) xxp = tuplecs.toReference(xxp);
float[][] xxm = {{xx[0][0]}, {xx[1][0]}, {xx[2][0]}};
xxm[otherindex][0] -= EPS;
if (tuplecs != null) xxm = tuplecs.toReference(xxm);
double dot = (xxp[0][0] - xxm[0][0]) * direction[0] +
(xxp[1][0] - xxm[1][0]) * direction[1] +
(xxp[2][0] - xxm[2][0]) * direction[2];
float abs = (float)
Math.sqrt((xxp[0][0] - xxm[0][0]) * (xxp[0][0] - xxm[0][0]) +
(xxp[1][0] - xxm[1][0]) * (xxp[1][0] - xxm[1][0]) +
(xxp[2][0] - xxm[2][0]) * (xxp[2][0] - xxm[2][0]));
float other_offset = EPS * (2.0f * EPS / abs);
if (dot >= 0.0) other_offset = -other_offset;
last_x =
new float[][] {{clast_x[0][0]}, {clast_x[1][0]}, {clast_x[2][0]}};
if (Display.DisplaySpatialSphericalTuple.equals(tuple) &&
otherindex != 1) {
if (last_x[1][0] < first_x[1][0] && cum_lon > 0.0f) {
last_x[1][0] += 360.0;
}
else if (last_x[1][0] > first_x[1][0] && cum_lon < 0.0f) {
last_x[1][0] -= 360.0;
}
}
int npoints = 4 * EDGE + 1;
float[][] c = new float[3][npoints];
for (int i=0; i 1) ? InputEvent.CTRL_MASK : 0;
display.addReferences(new RubberBandBoxRendererJ3D(x, y, m, m), ref);
CellImpl cell = new CellImpl() {
public void doAction() throws VisADException, RemoteException {
Set set = (Set) ref.getData();
float[][] samples = set.getSamples();
if (samples != null) {
System.out.println("box (" + samples[0][0] + ", " + samples[1][0] +
") to (" + samples[0][1] + ", " + samples[1][1] + ")");
}
}
};
cell.addReference(ref);
// create JFrame (i.e., a window) for display and slider
JFrame frame = new JFrame("test RubberBandBoxRendererJ3D");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
// create JPanel in JFrame
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);
// add display to JPanel
panel.add(display.getComponent());
// set size of JFrame and make it visible
frame.setSize(500, 500);
frame.setVisible(true);
}
}
Ads help maintain this website.