Exemplo n.º 1
0
  /**
   * Set the sounding in the table
   *
   * @param sounding the sounding
   * @throws RemoteException Java RMI problem
   * @throws VisADException problem dissecting data
   */
  private void setSounding(Field sounding) throws VisADException, RemoteException {
    domainData = null;

    // domain values
    Set domain = sounding.getDomainSet();
    CoordinateSystem cs = domain.getCoordinateSystem();

    float[][] domSamples = domain.getSamples(false);
    if ((cs != null)) {
      float[][] domFloats = Set.copyFloats(domSamples);
      // Must convert from the default coordinate domain system to
      // the domain coordinate system of the sounding.
      String fromUnit = sounding.getDomainUnits()[0].toString();
      String toUnit = cs.getCoordinateSystemUnits()[0].toString();
      if (!fromUnit.equals(toUnit) && SimpleUnit.isCompatible(fromUnit, toUnit)) {
        float conversionFactor = (float) SimpleUnit.getConversionFactor(fromUnit, toUnit);
        for (int i = 0; i < domFloats.length; i++) {
          for (int j = 0; j < domFloats[i].length; j++) {
            domFloats[i][j] = domFloats[i][j] * conversionFactor;
          }
        }
      }
      float[][] refData = cs.toReference(domFloats);
      domainData = new float[][] {domSamples[0], refData[0]};
    }
    // range values
    RealType[] rangeComps = ((FunctionType) sounding.getType()).getRealComponents();
    rangeData = sounding.getFloats(false);

    // wind
    if (rangeComps.length > 2) {
      transformWinds = (showUAndV && !haveUV) || (!showUAndV && haveUV);
      if (!transformWinds) {
        for (int i = 2; i < 4; i++) {
          columnNames[numDomainCols + i] =
              makeColumnName(rangeComps[i], rangeComps[i].getDefaultUnit());
        }
      } else {
        RealTupleType refType = windTransform.getReference();
        Unit[] refUnits = windTransform.getReferenceUnits();
        for (int i = 0; i < 2; i++) {
          columnNames[numDomainCols + i + 2] =
              makeColumnName((RealType) refType.getComponent(i), refUnits[i]);
        }
        float[][] newVals =
            windTransform.toReference(Set.copyFloats(new float[][] {rangeData[2], rangeData[3]}));
        rangeData[2] = newVals[0];
        rangeData[3] = newVals[1];
      }
    }
    sorter.setTableModel(model);
  }
Exemplo n.º 2
0
  // compute the lat/long limits for fetching data; invert the Y axis, too.
  private void computeLimits() {

    // Now set lat/lon limits...

    float[][] linele = {
      {(float) xfirst, (float) xlast, (float) xlast, (float) xfirst},
      {(float) yfirst, (float) yfirst, (float) ylast, (float) ylast}
    };

    float[][] latlon;

    try {

      latlon = cs.toReference(linele);

      if (Float.isNaN(latlon[0][0])) latlon[0][0] = 90.f;
      if (Float.isNaN(latlon[1][0])) latlon[1][0] = 180.f;

      if (Float.isNaN(latlon[0][1])) latlon[0][1] = 90.f;
      if (Float.isNaN(latlon[1][1])) latlon[1][1] = -180.f;

      if (Float.isNaN(latlon[0][2])) latlon[0][2] = -90.f;
      if (Float.isNaN(latlon[1][2])) latlon[1][2] = 180.f;

      if (Float.isNaN(latlon[0][3])) latlon[0][3] = -90.f;
      if (Float.isNaN(latlon[1][3])) latlon[1][3] = -180.f;

      /*
      for (int i=0; i<4; i++) {
        System.out.println("Point "+i+"  Line/Ele="+linele[0][i]+" "+
          linele[1][i]+" Lat/long="+ latlon[0][i]+" "+latlon[1][i]);
      }
      */

      setLatLonLimits(
          Math.min(latlon[0][0], Math.min(latlon[0][1], Math.min(latlon[0][2], latlon[0][3]))),
          Math.max(latlon[0][0], Math.max(latlon[0][1], Math.max(latlon[0][2], latlon[0][3]))),
          Math.min(latlon[1][0], Math.min(latlon[1][1], Math.min(latlon[1][2], latlon[1][3]))),
          Math.max(latlon[1][0], Math.max(latlon[1][1], Math.max(latlon[1][2], latlon[1][3]))));
    } catch (Exception ell) {
      System.out.println(ell);
    }

    isCoordinateSystem = true;
  }
Exemplo n.º 3
0
  /**
   * @param grid The grid.
   * @param gridWinds The grid-relative winds.
   * @param cs The coordinate system transformation of the grid.
   * @param index The index of the grid-relative wind component.
   * @param latI The index of latitude in the reference coordinate system.
   * @param lonI The index of longitude in the reference coordinate system.
   * @param us The array in which to add the computed U-component of the wind.
   * @param us The array in which to add the computed V-component of the wind.
   * @param vs
   * @throws IndexOutOfBoundsException if <code>gridWinds</code>, <code>us
   *                                   </code>, or <code>vs</code> is too small.
   * @throws VisADException if a VisAD failure occurs.
   */
  private static void addComponent(
      SampledSet grid,
      float[][] gridWinds,
      CoordinateSystem cs,
      int index,
      int latI,
      int lonI,
      float[] us,
      float[] vs)
      throws VisADException {

    int[][] neighbors = grid.getNeighbors(index);
    LatLonPointImpl refPt = new LatLonPointImpl();
    LatLonPointImpl neiPt = new LatLonPointImpl();
    Bearing bearing = new Bearing();
    float[] uv1 = new float[2];
    float[] uv2 = new float[2];
    boolean hasCS = cs != null;
    float[][] domainSamples = grid.getSamples(false);
    float[][] crefCoords = (hasCS) ? cs.toReference(Set.copyFloats(domainSamples)) : domainSamples;
    // If the grid is lat/lon or has an IdentityCoordinateSystem
    // don't do the rotation
    // TODO:  handle rotated lat/lon grids
    if (!hasCS
        || (crefCoords == domainSamples)
        || (Arrays.equals(crefCoords[latI], domainSamples[latI])
            && Arrays.equals(crefCoords[lonI], domainSamples[lonI]))) {
      // us = gridWinds[0];
      // vs = gridWinds[1];
      System.arraycopy(gridWinds[0], 0, us, 0, us.length);
      System.arraycopy(gridWinds[1], 0, vs, 0, vs.length);
    } else {

      for (int i = 0; i < neighbors.length; i++) {

        float[][] refCoords = grid.indexToValue(new int[] {i});
        if (hasCS) {
          refCoords = cs.toReference(refCoords);
        }

        float[][] neiCoords = grid.indexToValue(neighbors[i]);
        if (hasCS) {
          neiCoords = cs.toReference(neiCoords);
        }

        refPt.set(refCoords[latI][0], refCoords[lonI][0]);

        compute(
            refPt,
            neiPt,
            neiCoords[latI][0],
            neiCoords[lonI][0],
            -180,
            gridWinds[index][i],
            bearing,
            uv1);

        float d1 = (float) bearing.getDistance();

        compute(
            refPt,
            neiPt,
            neiCoords[latI][1],
            neiCoords[lonI][1],
            0,
            gridWinds[index][i],
            bearing,
            uv2);

        float d2 = (float) bearing.getDistance();
        boolean bad1 = Double.isNaN(d1);
        boolean bad2 = Double.isNaN(d2);

        if (bad1 && bad2) {
          us[i] = Float.NaN;
          vs[i] = Float.NaN;
        } else {
          if (bad1) {
            us[i] += uv2[0];
            vs[i] += uv2[1];
          } else if (bad2) {
            us[i] += uv1[0];
            vs[i] += uv1[1];
          } else {
            float tot = d1 + d2;
            float c1 = d2 / tot;
            float c2 = d1 / tot;

            us[i] += c1 * uv1[0] + c2 * uv2[0];
            vs[i] += c1 * uv1[1] + c2 * uv2[1];
          }
        }
      }
    }
  }
Exemplo n.º 4
0
  /**
   * I have no idea what this does.
   *
   * @param grid sampling grid
   * @param index some sort of index
   * @return a new flat field with something different
   * @throws RemoteException Java RMI error
   * @throws VisADException VisAD error
   */
  private static FlatField hatFieldOld(Set grid, int index) throws VisADException, RemoteException {

    CoordinateSystem cs = grid.getCoordinateSystem();
    boolean hasCS = (cs != null);

    RealTupleType rtt = (hasCS) ? cs.getReference() : ((SetType) grid.getType()).getDomain();

    int latI = rtt.getIndex(RealType.Latitude);

    if (latI == -1) {
      throw new IllegalArgumentException(grid.toString());
    }

    int lonI = rtt.getIndex(RealType.Longitude);

    if (lonI == -1) {
      throw new IllegalArgumentException(grid.toString());
    }

    if (grid.getManifoldDimension() < 2) {
      throw new IllegalArgumentException(grid.toString());
    }

    int[][] neighbors = grid.getNeighbors(index);
    LatLonPointImpl refPt = new LatLonPointImpl();
    LatLonPointImpl neiPt = new LatLonPointImpl();
    Bearing bearing = new Bearing();
    float[] hat1 = new float[2];
    float[] hat2 = new float[2];
    float[][] hat = new float[2][grid.getLength()];

    for (int i = 0; i < neighbors.length; i++) {
      float[][] refCoords = grid.indexToValue(new int[] {i});
      if (hasCS) {
        refCoords = cs.toReference(refCoords);
      }

      float[][] neiCoords = grid.indexToValue(neighbors[i]);
      if (hasCS) {
        neiCoords = cs.toReference(neiCoords);
      }

      refPt.set(refCoords[latI][0], refCoords[lonI][0]);
      compute(refPt, neiPt, neiCoords[latI][0], neiCoords[lonI][0], -180, bearing, hat1);

      float d1 = (float) bearing.getDistance();

      compute(refPt, neiPt, neiCoords[latI][1], neiCoords[lonI][1], 0, bearing, hat2);

      float d2 = (float) bearing.getDistance();
      boolean bad1 = Double.isNaN(d1);
      boolean bad2 = Double.isNaN(d2);

      if (bad1 && bad2) {
        hat[0][i] = Float.NaN;
        hat[1][i] = Float.NaN;
      } else {
        if (bad1) {
          hat[0][i] = hat2[0];
          hat[1][i] = hat2[1];
        } else if (bad2) {
          hat[0][i] = hat1[0];
          hat[1][i] = hat1[1];
        } else {
          float tot = d1 + d2;
          float c1 = d2 / tot;
          float c2 = d1 / tot;
          float xhat = c1 * hat1[0] + c2 * hat2[0];
          float yhat = c1 * hat1[1] + c2 * hat2[1];
          float mag = (float) Math.sqrt(xhat * xhat + yhat * yhat);

          hat[0][i] = xhat / mag;
          hat[1][i] = yhat / mag;
        }
      }
    }

    FlatField hatField =
        new FlatField(
            new FunctionType(
                ((SetType) grid.getType()).getDomain(),
                new RealTupleType(
                    RealType.getRealType("xHat", CommonUnit.dimensionless),
                    RealType.getRealType("yHat", CommonUnit.dimensionless))),
            grid);

    hatField.setSamples(hat, false);

    return hatField;
  }
Exemplo n.º 5
0
  /**
   * The returned {@link visad.FlatField} will have NaN-s for those unit vector components that
   * could not be computed.
   *
   * @param grid The spatial grid.
   * @param index The index of the manifold dimension along which to compute the unit vector.
   * @return A field of components of the unit vector for the given manifold dimension.
   * @throws NullPointerException if the grid is <code>null</code>.
   * @throws IllegalArgumentException if the manifold dimension of the grid is less than 2 or if the
   *     grid doesn't contain {@link visad.RealType#Latitude} and {@link visad.RealType#Longitude}.
   * @throws VisADException if a VisAD failure occurs.
   * @throws RemoteException if a Java RMI failure occurs.
   */
  private static FlatField hatFieldNew(Set grid, int index) throws VisADException, RemoteException {

    CoordinateSystem cs = grid.getCoordinateSystem();
    boolean hasCS = cs != null;

    RealTupleType rtt = (hasCS) ? cs.getReference() : ((SetType) grid.getType()).getDomain();

    int latI = rtt.getIndex(RealType.Latitude);

    if (latI == -1) {
      throw new IllegalArgumentException(rtt.toString());
    }

    int lonI = rtt.getIndex(RealType.Longitude);
    if (lonI == -1) {
      throw new IllegalArgumentException(rtt.toString());
    }

    if (grid.getManifoldDimension() < 2) {
      throw new IllegalArgumentException(grid.toString());
    }

    int[][] neighbors = grid.getNeighbors(index);
    LatLonPointImpl refPt = new LatLonPointImpl();
    LatLonPointImpl neiPt = new LatLonPointImpl();
    Bearing bearing = new Bearing();
    float[] hat1 = new float[2];
    float[] hat2 = new float[2];
    float[][] hat = new float[2][grid.getLength()];

    float[][] refCoords = null;
    float[][] neiCoords = null;
    float[][] domainSamples = grid.getSamples(false);

    refCoords = (hasCS) ? cs.toReference(Set.copyFloats(domainSamples)) : domainSamples;
    // If the grid is lat/lon or has an IdentityCoordinateSystem
    // don't do the rotation
    // TODO:  handle rotated lat/lon grids
    if (!hasCS
        || (refCoords == domainSamples)
        || (Arrays.equals(refCoords[latI], domainSamples[latI])
            && Arrays.equals(refCoords[lonI], domainSamples[lonI]))) {
      if (index == 0) {
        Arrays.fill(hat[0], 1);
        Arrays.fill(hat[1], 0);
      } else {
        Arrays.fill(hat[0], 0);
        Arrays.fill(hat[1], 1);
      }
    } else {

      float latBefore, lonBefore, latAfter, lonAfter;
      // int backOffset = (index==0) ? -180 : 0;
      // int foreOffset = (index==0) ? 0 : -180;
      int backOffset = -180;
      int foreOffset = 0;
      for (int i = 0; i < neighbors.length; i++) {
        refPt.set(refCoords[latI][i], refCoords[lonI][i]);
        if ((neighbors[i][0] < 0) || (neighbors[i][0] >= neighbors.length)) {
          latBefore = Float.NaN;
          lonBefore = Float.NaN;
        } else {
          latBefore = refCoords[latI][neighbors[i][0]];
          lonBefore = refCoords[lonI][neighbors[i][0]];
        }
        if ((neighbors[i][1] < 0) || (neighbors[i][1] >= neighbors.length)) {
          latAfter = Float.NaN;
          lonAfter = Float.NaN;
        } else {
          latAfter = refCoords[latI][neighbors[i][1]];
          lonAfter = refCoords[lonI][neighbors[i][1]];
        }

        compute(refPt, neiPt, latBefore, lonBefore, backOffset, bearing, hat1);

        float d1 = (float) bearing.getDistance();

        compute(refPt, neiPt, latAfter, lonAfter, foreOffset, bearing, hat2);

        float d2 = (float) bearing.getDistance();
        boolean bad1 = Double.isNaN(d1);
        boolean bad2 = Double.isNaN(d2);

        if (bad1 && bad2) {
          hat[0][i] = Float.NaN;
          hat[1][i] = Float.NaN;
        } else {
          if (bad1) {
            hat[0][i] = hat2[0];
            hat[1][i] = hat2[1];
          } else if (bad2) {
            hat[0][i] = hat1[0];
            hat[1][i] = hat1[1];
          } else {
            float tot = d1 + d2;
            float c1 = d2 / tot;
            float c2 = d1 / tot;
            float xhat = c1 * hat1[0] + c2 * hat2[0];
            float yhat = c1 * hat1[1] + c2 * hat2[1];
            float mag = (float) Math.sqrt(xhat * xhat + yhat * yhat);

            hat[0][i] = xhat / mag;
            hat[1][i] = yhat / mag;
          }
        }
      }
    }

    FlatField hatField =
        new FlatField(
            new FunctionType(
                ((SetType) grid.getType()).getDomain(),
                new RealTupleType(
                    RealType.getRealType("xHat", CommonUnit.dimensionless),
                    RealType.getRealType("yHat", CommonUnit.dimensionless))),
            grid);

    hatField.setSamples(hat, false);
    return hatField;
  }
Exemplo n.º 6
0
  /**
   * Make a grid with a Linear3DSet for the volume rendering
   *
   * @param grid grid to transform
   * @param cs coordinate system to transform to XYZ
   * @return transformed grid
   * @throws RemoteException Java RMI Exception
   * @throws VisADException problem creating grid
   */
  private FieldImpl makeLinearGrid(FieldImpl grid, CoordinateSystem cs)
      throws VisADException, RemoteException {

    Trace.call1("VRC.makeLinearGrid");
    GriddedSet domainSet = (GriddedSet) GridUtil.getSpatialDomain(grid);
    SampledSet ss = null;
    boolean latLonOrder = GridUtil.isLatLonOrder(domainSet);
    // System.out.println("grid is latLonOrder " + latLonOrder);
    Trace.call1("VRC.convertDomain");
    if (latLonOrder) {
      ss = Util.convertDomain(domainSet, RealTupleType.LatitudeLongitudeAltitude, null);
    } else {
      ss = Util.convertDomain(domainSet, RealTupleType.SpatialEarth3DTuple, null);
    }
    Trace.call2("VRC.convertDomain");
    float[][] refVals = ss.getSamples(true);
    MapProjectionDisplay mpd = (MapProjectionDisplay) getNavigatedDisplay();
    MapProjection mp = mpd.getMapProjection();
    boolean mapLatLonOrder = mp.isLatLonOrder();
    // System.out.println("map is latLonOrder " + mapLatLonOrder);
    float[][] newVals =
        (latLonOrder) ? refVals : new float[][] {refVals[1], refVals[0], refVals[2]};
    Trace.call1("VRC.toRef");
    newVals = cs.toReference(newVals);
    Trace.call2("VRC.toRef");
    Trace.call1("VRC.scaleVerticalValues");
    newVals[2] = mpd.scaleVerticalValues(newVals[2]);
    Trace.call2("VRC.scaleVerticalValues");
    int[] lengths = domainSet.getLengths();
    // Misc.printArray("lengths",lengths);
    GriddedSet xyzSet =
        GriddedSet.create(
            RealTupleType.SpatialCartesian3DTuple,
            newVals,
            domainSet.getLengths(),
            (CoordinateSystem) null,
            (Unit[]) null,
            (ErrorEstimate[]) null,
            false,
            true);
    Trace.call1("VRC.setSpatialDomain");
    FieldImpl newGrid = GridUtil.setSpatialDomain(grid, xyzSet); // , true);
    Trace.call2("VRC.setSpatialDomain");
    float[] lows = xyzSet.getLow();
    float[] highs = xyzSet.getHi();
    // Misc.printArray("lows",lows);
    // Misc.printArray("highs",highs);
    Linear3DSet volumeXYZ =
        new Linear3DSet(
            RealTupleType.SpatialCartesian3DTuple,
            lows[0],
            highs[0],
            lengths[0],
            lows[1],
            highs[1],
            lengths[1],
            lows[2],
            highs[2],
            lengths[2]);
    // System.out.println(volumeXYZ);
    Trace.call1("VRC.resampleGrid");
    newGrid = GridUtil.resampleGrid(newGrid, volumeXYZ);
    Trace.call2("VRC.resampleGrid");
    Trace.call2("VRC.makeLinearGrid");
    return newGrid;
  }
Exemplo n.º 7
0
  public synchronized void drag_direct(VisADRay ray, boolean first, int mouseModifiers) {
    if (barbValues == null || ref == null || shadow == null) return;

    if (first) {
      stop = false;
    } else {
      if (stop) return;
    }

    // modify direction if mshift != 0
    // modify speed if mctrl != 0
    // modify speed and direction if neither
    int mshift = mouseModifiers & InputEvent.SHIFT_MASK;
    int mctrl = mouseModifiers & InputEvent.CTRL_MASK;

    float o_x = (float) ray.position[0];
    float o_y = (float) ray.position[1];
    float o_z = (float) ray.position[2];
    float d_x = (float) ray.vector[0];
    float d_y = (float) ray.vector[1];
    float d_z = (float) ray.vector[2];

    if (pickCrawlToCursor) {
      if (first) {
        offset_count = OFFSET_COUNT_INIT;
      } else {
        if (offset_count > 0) offset_count--;
      }
      if (offset_count > 0) {
        float mult = ((float) offset_count) / ((float) OFFSET_COUNT_INIT);
        o_x += mult * offsetx;
        o_y += mult * offsety;
        o_z += mult * offsetz;
      }
    }

    if (first || refirst) {
      point_x = barbValues[2];
      point_y = barbValues[3];
      point_z = 0.0f;
      line_x = 0.0f;
      line_y = 0.0f;
      line_z = 1.0f; // lineAxis == 2 in DataRenderer.drag_direct
    } // end if (first || refirst)

    float[] x = new float[3]; // x marks the spot
    // DirectManifoldDimension = 2
    // intersect ray with plane
    float dot = (point_x - o_x) * line_x + (point_y - o_y) * line_y + (point_z - o_z) * line_z;
    float dot2 = d_x * line_x + d_y * line_y + d_z * line_z;
    if (dot2 == 0.0) return;
    dot = dot / dot2;
    // x is intersection
    x[0] = o_x + dot * d_x;
    x[1] = o_y + dot * d_y;
    x[2] = o_z + dot * d_z;
    /*
    System.out.println("x = " + x[0] + " " + x[1] + " " + x[2]);
    */
    try {

      Tuple data = (Tuple) link.getData();
      int n = ((TupleType) data.getType()).getNumberOfRealComponents();
      Real[] reals = new Real[n];

      int k = 0;
      int m = data.getDimension();
      for (int i = 0; i < m; i++) {
        Data component = data.getComponent(i);
        if (component instanceof Real) {
          reals[k++] = (Real) component;
        } else if (component instanceof RealTuple) {
          for (int j = 0; j < ((RealTuple) component).getDimension(); j++) {
            reals[k++] = (Real) ((RealTuple) component).getComponent(j);
          }
        }
      }

      if (first || refirst) {
        // get first Data flow vector
        for (int i = 0; i < 3; i++) {
          int j = flowToComponent[i];
          data_flow[i] = (j >= 0) ? (float) reals[j].getValue() : 0.0f;
        }

        if (coord != null) {
          float[][] ds = {{data_flow[0]}, {data_flow[1]}, {data_flow[2]}};
          ds = coord.toReference(ds);
          data_flow[0] = ds[0][0];
          data_flow[1] = ds[1][0];
          data_flow[2] = ds[2][0];
        }

        data_speed =
            (float)
                Math.sqrt(
                    data_flow[0] * data_flow[0]
                        + data_flow[1] * data_flow[1]
                        + data_flow[2] * data_flow[2]);
        float barb0 = barbValues[2] - barbValues[0];
        float barb1 = barbValues[3] - barbValues[1];
        /*
        System.out.println("data_flow = " + data_flow[0] + " " + data_flow[1] +
                           " " + data_flow[2]);
        System.out.println("barbValues = " + barbValues[0] + " " + barbValues[1] +
                           "   " + barbValues[2] + " " + barbValues[3]);
        System.out.println("data_speed = " + data_speed);
        */
      } // end if (first || refirst)

      // convert x to a flow vector, and from spatial to earth
      if (getRealVectorTypes(which_barb) instanceof EarthVectorType) {
        // don't worry about vector magnitude -
        // data_speed & display_speed take care of that
        float eps = 0.0001f; // estimate derivative with a little vector
        float[][] spatial_locs = {
          {barbValues[0], barbValues[0] + eps * (x[0] - barbValues[0])},
          {barbValues[1], barbValues[1] + eps * (x[1] - barbValues[1])},
          {0.0f, 0.0f}
        };
        /*
        System.out.println("spatial_locs = " + spatial_locs[0][0] + " " +
                           spatial_locs[0][1] + " " + spatial_locs[1][0] + " " +
                           spatial_locs[1][1]);
        */
        float[][] earth_locs = spatialToEarth(spatial_locs);
        // WLH - 18 Aug 99
        if (earth_locs == null) return;
        /*
        System.out.println("earth_locs = " + earth_locs[0][0] + " " +
                           earth_locs[0][1] + " " + earth_locs[1][0] + " " +
                           earth_locs[1][1]);
        */
        x[2] = 0.0f;
        x[0] =
            (earth_locs[1][1] - earth_locs[1][0])
                * ((float) Math.cos(Data.DEGREES_TO_RADIANS * earth_locs[0][0]));
        x[1] = earth_locs[0][1] - earth_locs[0][0];
        /*
        System.out.println("x = " + x[0] + " " + x[1] + " " + x[2]);
        */
      } else { // if (!(getRealVectorTypes(which_barb) instanceof EarthVectorType))
        // convert x to vector
        x[0] -= barbValues[0];
        x[1] -= barbValues[1];

        // adjust for spatial map scalings but don't worry about vector
        // magnitude - data_speed & display_speed take care of that
        // also, spatial is Cartesian
        double[] ranges = getRanges();
        for (int i = 0; i < 3; i++) {
          x[i] /= ranges[i];
        }
        /*
        System.out.println("ranges = " + ranges[0] + " " + ranges[1] +
                           " " + ranges[2]);
        System.out.println("x = " + x[0] + " " + x[1] + " " + x[2]);
        */
      }

      // WLH 6 August 99
      x[0] = -x[0];
      x[1] = -x[1];
      x[2] = -x[2];

      /* may need to do this for performance
            float[] xx = {x[0], x[1], x[2]};
            addPoint(xx);
      */

      float x_speed = (float) Math.sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
      /* WLH 16 April 2002 - from Ken
            if (x_speed < 0.000001f) x_speed = 0.000001f;
      */
      if (x_speed < 0.01f) x_speed = 0.01f;
      if (first || refirst) {
        display_speed = x_speed;
      }
      refirst = false;

      if (mshift != 0) {
        // only modify data_flow direction
        float ratio = data_speed / x_speed;
        x[0] *= ratio;
        x[1] *= ratio;
        x[2] *= ratio;
        /*
        System.out.println("direction, ratio = " + ratio + " " +
                           data_speed + " " + x_speed);
        System.out.println("x = " + x[0] + " " + x[1] + " " + x[2]);
        */
      } else if (mctrl != 0) {
        // only modify data_flow speed
        float ratio = x_speed / display_speed;
        if (data_speed < EPS) {
          data_flow[0] = 2.0f * EPS;
          refirst = true;
        }
        x[0] = ratio * data_flow[0];
        x[1] = ratio * data_flow[1];
        x[2] = ratio * data_flow[2];
        /*
        System.out.println("speed, ratio = " + ratio + " " +
                           x_speed + " " + display_speed);
        System.out.println("x = " + x[0] + " " + x[1] + " " + x[2]);
        */
      } else {
        // modify data_flow speed and direction
        float ratio = data_speed / display_speed;
        /*
        System.out.println("data_speed = " + data_speed +
                           " display_speed = " + display_speed +
                           " ratio = " + ratio + " EPS = " + EPS);
        System.out.println("x = " + x[0] + " " + x[1] +" " + x[2] +
                           " x_speed = " + x_speed);
          data_speed = 21.213203 display_speed = 0.01 ratio = 2121.3203 EPS = 0.2
          x = 1.6170928E-4 1.6021729E-4 -0.0 x_speed = 0.01
          wind = (0.3430372, 0.33987218) at (-35.0, 5.0)
        */
        if (data_speed < EPS) {
          data_flow[0] = 2.0f * EPS;
          x[0] = data_flow[0];
          x[1] = data_flow[1];
          x[2] = data_flow[2];
          refirst = true;
        } else {
          x[0] *= ratio;
          x[1] *= ratio;
          x[2] *= ratio;
        }
      }

      if (coord != null) {
        float[][] xs = {{x[0]}, {x[1]}, {x[2]}};
        xs = coord.fromReference(xs);
        x[0] = xs[0][0];
        x[1] = xs[1][0];
        x[2] = xs[2][0];
      }

      // now replace flow values
      Vector vect = new Vector();
      for (int i = 0; i < 3; i++) {
        int j = flowToComponent[i];
        if (j >= 0) {
          RealType rtype = (RealType) reals[j].getType();
          reals[j] = new Real(rtype, (double) x[i], rtype.getDefaultUnit(), null);

          // WLH 31 Aug 2000
          Real r = reals[j];
          Unit overrideUnit = null;
          if (directMap[i] != null) {
            overrideUnit = directMap[i].getOverrideUnit();
          }
          Unit rtunit = rtype.getDefaultUnit();
          // units not part of Time string
          if (overrideUnit != null
              && !overrideUnit.equals(rtunit)
              && !RealType.Time.equals(rtype)) {
            double d = (float) overrideUnit.toThis((double) x[0], rtunit);
            r = new Real(rtype, d, overrideUnit);
            String valueString = r.toValueString();
            vect.addElement(rtype.getName() + " = " + valueString);
          } else {
            // create location string
            vect.addElement(rtype.getName() + " = " + x[i]);
          }
        }
      }
      getDisplayRenderer().setCursorStringVector(vect);

      Data newData = null;
      // now build new RealTuple or Flat Tuple
      if (data instanceof RealTuple) {
        newData =
            new RealTuple(
                ((RealTupleType) data.getType()), reals, ((RealTuple) data).getCoordinateSystem());
      } else {
        Data[] new_components = new Data[m];
        k = 0;
        for (int i = 0; i < m; i++) {
          Data component = data.getComponent(i);
          if (component instanceof Real) {
            new_components[i] = reals[k++];
          } else if (component instanceof RealTuple) {
            Real[] sub_reals = new Real[((RealTuple) component).getDimension()];
            for (int j = 0; j < ((RealTuple) component).getDimension(); j++) {
              sub_reals[j] = reals[k++];
            }
            new_components[i] =
                new RealTuple(
                    ((RealTupleType) component.getType()),
                    sub_reals,
                    ((RealTuple) component).getCoordinateSystem());
          }
        }
        newData = new Tuple(new_components, false);
      }
      ref.setData(newData);
    } catch (VisADException e) {
      // do nothing
      System.out.println("drag_direct " + e);
      e.printStackTrace();
    } catch (RemoteException e) {
      // do nothing
      System.out.println("drag_direct " + e);
      e.printStackTrace();
    }
  }