//
// CurveManipulationRendererJ2D.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.java2d.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.rmi.*;
/**
* CurveManipulationRendererJ2D is the VisAD class for direct
* manipulation rendering of curves under Java2D, where curves
* are represented by UnionSets of Gridded2DSets with manifold
* dimension = 2
*/
public class CurveManipulationRendererJ2D extends DirectManipulationRendererJ2D {
private int mouseModifiersMask = 0;
private int mouseModifiersValue = 0;
private boolean only_one = false;
/**
* Construct a DataRenderer that supports direct manipulation of
* representations of curves by UnionSets of Gridded2DSets
* with manifold dimension = 2; the Set's domain RealTypes
* must be mapped to (XAxis, YAxis);
*/
public CurveManipulationRendererJ2D () {
this(0, 0);
}
/**
* Construct a DataRenderer that supports direct manipulation of
* representations of curves by UnionSets of Gridded2DSets
* with manifold dimension = 2; the Set's domain RealTypes
* must be mapped to (XAxis, YAxis).
* 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)
* @param mmm mouse modifiers
* @param mmv mouse mask to check.
*/
public CurveManipulationRendererJ2D (int mmm, int mmv) {
this(mmm, mmv, false);
}
/**
* Construct a DataRenderer that supports direct manipulation of
* representations of curves by UnionSets of Gridded2DSets
* with manifold dimension = 2; the Set's domain RealTypes
* must be mapped to (XAxis, YAxis).
* 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)
* @param mmm mouse modifiers
* @param mmv mouse mask to check.
* @param oo if true, only one curve should exist at any one time.
*/
public CurveManipulationRendererJ2D (int mmm, int mmv, boolean oo) {
super();
mouseModifiersMask = mmm;
mouseModifiersValue = mmv;
only_one = oo;
}
/**
* Create a ShadowType based on the SetType
* @param type SetType of UnionSet.
* @param link DataDisplayLink for DataReference
* @param parent Parent ShadowType
* @throws VisADException problem creating a VisAD object
* @throws RemoteException problem creating a remote object
*/
public ShadowType makeShadowSetType(
SetType type, DataDisplayLink link, ShadowType parent)
throws VisADException, RemoteException {
return new ShadowCurveSetTypeJ2D(type, link, parent);
}
private float[][] spatialValues = null;
/** index into spatialValues found by checkClose */
private int closeIndex = -1;
/** for use in drag_direct */
private transient DataDisplayLink link = null;
private transient DataReference ref = null;
private transient MathType type = null;
private transient ShadowSetType shadow = null;
private transient RealType[] domain_reals;
float[] default_values;
/** point on direct manifold line or plane */
private float point_x, point_y, point_z;
/** normalized direction of line or perpendicular to plane */
private float line_x, line_y, line_z;
/** 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;
/** mapping from spatial axes to tuple component */
private int[] axisToComponent = {-1, -1, -1};
/** mapping from spatial axes to ScalarMaps */
private ScalarMap[] directMap = {null, null, null};
/** dimension of direct manipulation
(always 2 for CurveManipulationRendererJ2D) */
private int directManifoldDimension = 2;
/** spatial DisplayTupleType other than
DisplaySpatialCartesianTuple */
DisplayTupleType tuple;
private CoordinateSystem tuplecs;
private int otherindex = -1;
private float othervalue;
/** possible values for whyNotDirect */
private final static String notSetType =
"not Set";
private final static String notTwoD =
"Set must have domain dimension = 2";
private final static String domainNotSpatial =
"domain must be mapped to spatial";
private final static String badCoordSysManifoldDim =
"directManifoldDimension must be 2 with spatial CoordinateSystem";
private boolean stop = false;
/** pick error offset, communicated from checkClose() to drag_direct() */
private float offsetx = 0.0f, offsety = 0.0f, offsetz = 0.0f;
/** count down to decay offset to 0.0 */
private int offset_count = 0;
/** initial offset_count */
private static final int OFFSET_COUNT_INIT = 30;
/**
* Check whether direct manipulation is possible for this Renderer.
* Set appropriate error conditions if not possible.
* @throws VisADException problem accessing information
* @throws RemoteException problem accessing information for remote objects
*/
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();
type = link.getType();
if (!(type instanceof SetType)) {
whyNotDirect = notSetType;
return;
}
RealTupleType real_tuple = ((SetType) type).getDomain();
domain_reals = real_tuple.getRealComponents();
shadow = (ShadowSetType) link.getShadow().getAdaptedShadowType();
ShadowRealTupleType domain = ((ShadowSetType) shadow).getDomain();
directMap = new ScalarMap[] {null, null, null};
ShadowRealType[] components = shadow.getDomain().getRealComponents();
if (components.length != 2) {
whyNotDirect = notTwoD;
return;
}
tuple = domain.getDisplaySpatialTuple();
if(!(Display.DisplaySpatialCartesianTuple.equals(tuple) ||
(tuple != null &&
tuple.getCoordinateSystem().getReference().equals(
Display.DisplaySpatialCartesianTuple)) )) {
whyNotDirect = domainNotSpatial;
return;
}
int[] indices = {-1, -1};
for (int i=0; i 0) ? default_values[index] :
(float) dreal.getDefaultValue();
if (Display.DisplaySpatialCartesianTuple.equals(tuple)) {
tuple = null;
tuplecs = null;
}
else {
tuplecs = tuple.getCoordinateSystem();
}
directManifoldDimension = 2;
setIsDirectManipulation(true);
}
private int getDirectManifoldDimension() {
return directManifoldDimension;
}
/**
* Get the error messages on why direct manipulation is not possible.
* @return error messages.
*/
public String getWhyNotDirect() {
return whyNotDirect;
}
private int getAxisToComponent(int i) {
return axisToComponent[i];
}
private ScalarMap getDirectMap(int i) {
return directMap[i];
}
/**
* Add a point to the data. Not used, but may be needed for
* performance.
* @param x point to add.
* @throws VisADException error occured.
*/
public void addPoint(float[] x) throws VisADException {
// may need to do this for performance
}
// methods customized from DataRenderer:
/**
* Set spatialValues from ShadowType.doTransform
* @param spatial_values spatial values.
*/
public synchronized void setSpatialValues(float[][] spatial_values) {
spatialValues = spatial_values;
}
/**
* Find minimum distance from ray to spatialValues
* @param origin origin of ray
* @param direction direction of the ray
* @return miniumum distance from ray to spatial values
*/
public synchronized float checkClose(double[] origin, double[] direction) {
int mouseModifiers = getLastMouseModifiers();
if ((mouseModifiers & mouseModifiersMask) != mouseModifiersValue) {
return Float.MAX_VALUE;
}
float distance = Float.MAX_VALUE;
closeIndex = -1;
if (spatialValues != null) {
float o_x = (float) origin[0];
float o_y = (float) origin[1];
float o_z = (float) origin[2];
float d_x = (float) direction[0];
float d_y = (float) direction[1];
float d_z = (float) direction[2];
for (int i=0; i 0) offset_count--;
}
if (offset_count > 0) {
float mult = ((float) offset_count) / ((float) OFFSET_COUNT_INIT);
origin[0] += mult * offsetx;
origin[1] += mult * offsety;
origin[2] += mult * offsetz;
}
}
try {
float r = findRayManifoldIntersection(true, origin, direction, tuple,
otherindex, othervalue);
if (r != r) {
return;
}
float[][] xcs = {{(float) (origin[0] + r * direction[0])},
{(float) (origin[1] + r * direction[1])},
{(float) (origin[2] + r * direction[2])}};
float[] xx = {xcs[0][0], xcs[1][0], xcs[2][0]};
if (tuple != null) {
if (tuplecs == null) return;
xcs = tuplecs.fromReference(xcs);
}
float[] x = {xcs[0][0], xcs[1][0], xcs[2][0]};
addPoint(xx);
UnionSet data;
try {
data = (UnionSet) link.getData();
} catch (RemoteException re) {
if (visad.collab.CollabUtil.isDisconnectException(re)) {
getDisplay().connectionFailed(this, link);
removeLink(link);
return;
}
throw re;
}
if (data == null) return;
SampledSet[] sets = data.getSets();
int n = sets.length;
UnionSet newData = null;
// create location string
Vector vect = new Vector();
for (int i=0; i<3; i++) {
int j = getAxisToComponent(i);
if (j >= 0) {
f[0] = x[i];
// WLH 13 Feb 2001
ScalarMap dm = getDirectMap(i);
if (dm == null) return;
d = dm.inverseScaleValues(f);
// d = getDirectMap(i).inverseScaleValues(f);
value[j] = d[0];
RealType rtype = domain_reals[j];
// WLH 31 Aug 2000
Real rr = new Real(rtype, d[0]);
Unit overrideUnit = dm.getOverrideUnit(); // WLH 13 Feb 2001
// Unit overrideUnit = getDirectMap(i).getOverrideUnit();
Unit rtunit = rtype.getDefaultUnit();
// units not part of Time string
if (overrideUnit != null && !overrideUnit.equals(rtunit) &&
!RealType.Time.equals(rtype)) {
double dval = overrideUnit.toThis((double) d[0], rtunit);
rr = new Real(rtype, dval, overrideUnit);
}
String valueString = rr.toValueString();
vect.addElement(rtype.getName() + " = " + valueString);
}
}
getDisplayRenderer().setCursorStringVector(vect);
if (closeIndex < 0) {
if (first) {
if (only_one) {
SampledSet[] new_sets = new SampledSet[1];
float[][] new_samples = {{value[0]}, {value[1]}};
new_sets[0] = new Gridded2DSet(type, new_samples, 1,
data.getCoordinateSystem(),
data.getSetUnits(), null);
newData = new UnionSet(type, new_sets);
// System.out.println("drag_direct new");
}
else {
SampledSet[] new_sets = new SampledSet[n+1];
System.arraycopy(sets, 0, new_sets, 0, n);
float[][] new_samples = {{value[0]}, {value[1]}};
new_sets[n] = new Gridded2DSet(type, new_samples, 1,
data.getCoordinateSystem(),
data.getSetUnits(), null);
newData = new UnionSet(type, new_sets);
}
}
else { // !first
float[][] samples = sets[n-1].getSamples(false);
int m = samples[0].length;
float[][] new_samples = new float[2][m+1];
System.arraycopy(samples[0], 0, new_samples[0], 0, m);
System.arraycopy(samples[1], 0, new_samples[1], 0, m);
new_samples[0][m] = value[0];
new_samples[1][m] = value[1];
sets[n-1] = new Gridded2DSet(type, new_samples, m+1,
data.getCoordinateSystem(),
data.getSetUnits(), null);
newData = new UnionSet(type, sets);
}
}
else { // closeIndex >= 0
if (first) {
which_set = -1;
which_point = -1;
int w = closeIndex;
int len = 0;
for (int i=0; i 0) {
System.arraycopy(sets, 0, new_sets, 0, which_set);
}
if (k > 0) {
System.arraycopy(sets, which_set + 1, new_sets, which_set, k);
}
new_sets[n - 1] = sets[which_set];
return new_sets;
}
/**
* Clone this renderer.
* @return new Renderer with same parameters.
*/
public Object clone() {
return new CurveManipulationRendererJ2D(mouseModifiersMask,
mouseModifiersValue, only_one);
}
private static final int N = 64;
/** test CurveManipulationRendererJ2D */
public static void main(String args[])
throws VisADException, RemoteException {
RealType x = RealType.getRealType("x");
RealType y = RealType.getRealType("y");
RealTupleType xy = new RealTupleType(x, y);
RealType c = RealType.getRealType("c");
FunctionType ft = new FunctionType(xy, c);
// construct Java2D display and mappings
DisplayImpl display = new DisplayImplJ2D("display1");
display.addMap(new ScalarMap(x, Display.XAxis));
display.addMap(new ScalarMap(y, Display.YAxis));
display.addMap(new ScalarMap(c, Display.RGB));
DisplayRenderer displayRenderer = display.getDisplayRenderer();
displayRenderer.setBoxOn(false);
GraphicsModeControl mode = display.getGraphicsModeControl();
mode.setLineWidth(2.0f);
Integer2DSet fset = new Integer2DSet(xy, N, N);
FlatField field = new FlatField(ft, fset);
float[][] values = new float[1][N * N];
int k = 0;
for (int i=0; i 1);
CurveManipulationRendererJ2D cmr =
new CurveManipulationRendererJ2D(0, 0, only_one);
display.addReferences(cmr, ref);
// create JFrame (i.e., a window) for display and slider
JFrame frame = new JFrame("test CurveManipulationRendererJ2D");
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());
JPanel button_panel = new JPanel();
button_panel.setLayout(new BoxLayout(button_panel, BoxLayout.X_AXIS));
button_panel.setAlignmentY(JPanel.TOP_ALIGNMENT);
button_panel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
CurveDelete cd = new CurveDelete(ref, display);
if (!only_one) {
JButton del = new JButton("delete last");
del.addActionListener(cd);
del.setActionCommand("del");
button_panel.add(del);
}
JButton fill = new JButton("fill");
fill.addActionListener(cd);
fill.setActionCommand("fill");
button_panel.add(fill);
panel.add(button_panel);
/* Not available in Java 2D
JButton lines = new JButton("lines");
lines.addActionListener(cd);
lines.setActionCommand("lines");
button_panel.add(lines);
*/
panel.add(button_panel);
// set size of JFrame and make it visible
frame.setSize(500, 500);
frame.setVisible(true);
}
}
Ads help maintain this website.