//
// 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.