/** find minimum distance from ray to barb tail */ public synchronized float checkClose(double[] origin, double[] direction) { if (barbValues == null) return Float.MAX_VALUE; 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]; /* System.out.println("origin = " + o_x + " " + o_y + " " + o_z); System.out.println("direction = " + d_x + " " + d_y + " " + d_z); */ float x = barbValues[2] - o_x; float y = barbValues[3] - o_y; float z = 0.0f - o_z; float dot = x * d_x + y * d_y + z * d_z; x = x - dot * d_x; y = y - dot * d_y; z = z - dot * d_z; offsetx = x; offsety = y; offsetz = z; return (float) Math.sqrt(x * x + y * y + z * z); // distance }
/** * Get the curve length; assumes curve is float[2][len] and seg_length is float[len-1] * * @param curve the curve * @param seg_length the segment lengths * @return the length of the curve */ public static float curveLength(float[][] curve, float[] seg_length) { int len = curve[0].length; float curve_length = 0.0f; for (int i = 0; i < len - 1; i++) { seg_length[i] = (float) Math.sqrt( ((curve[0][i + 1] - curve[0][i]) * (curve[0][i + 1] - curve[0][i])) + ((curve[1][i + 1] - curve[1][i]) * (curve[1][i + 1] - curve[1][i]))); curve_length += seg_length[i]; } return curve_length; }
// type 'java Parallel' to run this application public static void main(String args[]) throws VisADException, RemoteException, IOException { RealType index = RealType.getRealType("index"); RealType[] coords = new RealType[NCOORDS]; for (int i = 0; i < NCOORDS; i++) { coords[i] = RealType.getRealType("coord" + i); } RealTupleType range = new RealTupleType(coords); FunctionType ftype = new FunctionType(index, range); Integer1DSet index_set = new Integer1DSet(NROWS); float[][] samples = new float[NCOORDS][NROWS]; for (int i = 0; i < NCOORDS; i++) { for (int j = 0; j < NROWS; j++) { samples[i][j] = (float) Math.random(); } } FlatField data = new FlatField(ftype, index_set); data.setSamples(samples, false); // create a 2-D Display using Java3D DisplayImpl display = new DisplayImplJ3D("display", new TwoDDisplayRendererJ3D()); parallel(display, data); // create JFrame (i.e., a window) for display and slider JFrame frame = new JFrame("Parallel Coordinates VisAD Application"); 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); }
/** * Create a front from the curve * * @param curve the curve coordinates * @param flip true to flip the pips * @return The front as a FieldImpl * @throws RemoteException On badness * @throws VisADException On badness */ private FieldImpl curveToFront(float[][] curve, boolean flip) throws VisADException, RemoteException { if (flipTheFlip) { flip = !flip; } // compute various scaling factors int len = curve[0].length; if (len < 2) { return null; } float[] seg_length = new float[len - 1]; float curve_length = curveLength(curve, seg_length); float delta = curve_length / (len - 1); // curve[findex] where // float findex = ibase + mul * repeat_shapes[shape][0][j] float mul = rprofile_length * zoom / rsegment_length; // curve_perp[][findex] * ratio * repeat_shapes[shape][1][j] float ratio = delta * mul; // compute unit perpendiculars to curve float[][] curve_perp = new float[2][len]; for (int i = 0; i < len; i++) { int im = i - 1; int ip = i + 1; if (im < 0) { im = 0; } if (ip > len - 1) { ip = len - 1; } float yp = curve[0][ip] - curve[0][im]; float xp = curve[1][ip] - curve[1][im]; xp = -xp; float d = (float) Math.sqrt(xp * xp + yp * yp); if (flip) { d = -d; } xp = xp / d; yp = yp / d; curve_perp[0][i] = xp; curve_perp[1][i] = yp; } // build Vector of FlatFields for each shape of each segment Vector inner_field_vector = new Vector(); for (int segment = 0; true; segment++) { // curve[findex] where // float findex = ibase + mul * repeat_shapes[shape][0][j] float segment_length = (segment == 0) ? fsegment_length : rsegment_length; int profile_length = (segment == 0) ? fprofile_length : rprofile_length; mul = profile_length * zoom / segment_length; // curve_perp[][findex] * ratio * repeat_shapes[shape][1][j] // float ratio = delta * mul; // figure out if clipping is needed for this segment // only happens for last segment boolean clip = false; float xclip = 0.0f; // int ibase = segment * profile_length; int ibase = (segment == 0) ? 0 : fprofile_length + (segment - 1) * rprofile_length; int iend = ibase + profile_length; if (ibase > len - 1) { break; } if (iend > len - 1) { clip = true; iend = len - 1; xclip = (iend - ibase) / mul; } // set up shapes for first or repeating segment int nshapes = nrshapes; float[][][] shapes = repeat_shapes; int[][][] tris = repeat_tris; float[] red = repeat_red; float[] green = repeat_green; float[] blue = repeat_blue; if (segment == 0) { nshapes = nfshapes; shapes = first_shapes; tris = first_tris; red = first_red; green = first_green; blue = first_blue; } // iterate over shapes for segment for (int shape = 0; shape < nshapes; shape++) { float[][] samples = shapes[shape]; int[][] ts = tris[shape]; /* // if needed, clip shape if (clip) { float[][][] outs = new float[1][][]; int[][][] outt = new int[1][][]; DelaunayCustom.clip(samples, ts, 1.0f, 0.0f, xclip, outs, outt); samples = outs[0]; ts = outt[0]; } */ if ((samples == null) || (samples[0].length < 1)) { break; } float[][] ss = mapShape(samples, len, ibase, mul, ratio, curve, curve_perp); // **** get rid of previous calls to fill() **** ts = DelaunayCustom.fill(ss); // jeffmc: For now don't clip. This seems to fix the problem of too short a front boolean DOCLIP = false; if (clip && DOCLIP) { float[][] clip_samples = { {xclip, xclip, xclip - CLIP_DELTA}, {CLIP_DELTA, -CLIP_DELTA, 0.0f} }; float[][] clip_ss = mapShape(clip_samples, len, ibase, mul, ratio, curve, curve_perp); // now solve for: // xc * clip_samples[0][0] + yc * clip_samples[1][0] = 1 // xc * clip_samples[0][1] + yc * clip_samples[1][1] = 1 // xc * clip_samples[0][2] + yc * clip_samples[1][2] < 1 float det = (clip_samples[0][1] * clip_samples[1][0] - clip_samples[0][0] * clip_samples[1][1]); float xc = (clip_samples[1][0] - clip_samples[1][1]) / det; float yc = (clip_samples[0][1] - clip_samples[0][0]) / det; float v = 1.0f; if (xc * clip_samples[0][2] + yc * clip_samples[1][2] > v) { xc = -xc; yc = -yc; v = -v; } float[][][] outs = new float[1][][]; int[][][] outt = new int[1][][]; DelaunayCustom.clip(ss, ts, xc, yc, v, outs, outt); ss = outs[0]; ts = outt[0]; } if (ss == null) { break; } int n = ss[0].length; // create color values for field float[][] values = new float[3][n]; float r = red[shape]; float g = green[shape]; float b = blue[shape]; for (int i = 0; i < n; i++) { values[0][i] = r; values[1][i] = g; values[2][i] = b; } // construct set and field DelaunayCustom delaunay = new DelaunayCustom(ss, ts); Irregular2DSet set = new Irregular2DSet(curve_type, ss, null, null, null, delaunay); FlatField field = new FlatField(front_inner, set); field.setSamples(values, false); inner_field_vector.addElement(field); // some crazy bug - see Gridded3DSet.makeNormals() } // end for (int shape=0; shape<nshapes; shape++) } // end for (int segment=0; true; segment++) int nfields = inner_field_vector.size(); Integer1DSet iset = new Integer1DSet(front_index, nfields); FieldImpl front = new FieldImpl(front_type, iset); FlatField[] fields = new FlatField[nfields]; for (int i = 0; i < nfields; i++) { fields[i] = (FlatField) inner_field_vector.elementAt(i); } front.setSamples(fields, false); return front; }
public float[] makeVector( boolean south, float x, float y, float z, float scale, float pt_size, float f0, float f1, float[] vx, float[] vy, float[] vz, int[] numv, float[] tx, float[] ty, float[] tz, int[] numt) { float wsp25, slant, barb, d, c195, s195; float x0, y0; float x1, y1, x2, y2, x3, y3; int nbarb50, nbarb10, nbarb5; float[] mbarb = new float[4]; mbarb[0] = x; mbarb[1] = y; if (getKnotsConvert()) { // convert meters per second to knots f0 *= (3600.0 / 1853.248); f1 *= (3600.0 / 1853.248); } float wnd_spd = (float) Math.sqrt(f0 * f0 + f1 * f1); int lenv = vx.length; int lent = tx.length; int nv = numv[0]; int nt = numt[0]; // determine the initial (minimum) length of the flag pole if (wnd_spd >= 2.5) { wsp25 = (float) Math.max(wnd_spd + 2.5, 5.0); slant = 0.15f * scale; barb = 0.4f * scale; // WLH 6 Aug 99 - barbs point the other way (duh) x0 = -f0 / wnd_spd; y0 = -f1 / wnd_spd; // plot the flag pole // lengthen to 'd = 3.0f * barb' // was 'd = barb' in original BOM code d = 3.0f * barb; x1 = (x + x0 * d); y1 = (y + y0 * d); /* // commented out in original BOM code vx[nv] = x; vy[nv] = y; vz[nv] = z; nv++; vx[nv] = x1; vy[nv] = y1; vz[nv] = z; nv++; // g.drawLine(x,y,x1,y1); */ // determine number of wind barbs needed for 10 and 50 kt winds nbarb50 = (int) (wsp25 / 50.f); nbarb10 = (int) ((wsp25 - (nbarb50 * 50.f)) / 10.f); nbarb5 = (int) ((wsp25 - (nbarb50 * 50.f) - (nbarb10 * 10.f)) / 5.f); // 2.5 to 7.5 kt winds are plotted with the barb part way done the pole if (nbarb5 == 1) { barb = barb * 0.4f; slant = slant * 0.4f; x1 = (x + x0 * d); y1 = (y + y0 * d); if (south) { x2 = (x + x0 * (d + slant) - y0 * barb); y2 = (y + y0 * (d + slant) + x0 * barb); } else { x2 = (x + x0 * (d + slant) + y0 * barb); y2 = (y + y0 * (d + slant) - x0 * barb); } vx[nv] = x1; vy[nv] = y1; vz[nv] = z; nv++; vx[nv] = x2; vy[nv] = y2; vz[nv] = z; nv++; // System.out.println("barb5 " + x1 + " " + y1 + "" + x2 + " " + y2); // g.drawLine(x1, y1, x2, y2); } // add a little more pole if (wsp25 >= 5.0f && wsp25 < 10.0f) { d = d + 0.125f * scale; x1 = (x + x0 * d); y1 = (y + y0 * d); /* WLH 24 April 99 vx[nv] = x; vy[nv] = y; vz[nv] = z; nv++; vx[nv] = x1; vy[nv] = y1; vz[nv] = z; nv++; */ // System.out.println("wsp25 " + x + " " + y + "" + x1 + " " + y1); // g.drawLine(x, y, x1, y1); } // now plot any 10 kt wind barbs barb = 0.4f * scale; slant = 0.15f * scale; for (int j = 0; j < nbarb10; j++) { d = d + 0.125f * scale; x1 = (x + x0 * d); y1 = (y + y0 * d); if (south) { x2 = (x + x0 * (d + slant) - y0 * barb); y2 = (y + y0 * (d + slant) + x0 * barb); } else { x2 = (x + x0 * (d + slant) + y0 * barb); y2 = (y + y0 * (d + slant) - x0 * barb); } vx[nv] = x1; vy[nv] = y1; vz[nv] = z; nv++; vx[nv] = x2; vy[nv] = y2; vz[nv] = z; nv++; // System.out.println("barb10 " + j + " " + x1 + " " + y1 + "" + x2 + " " + y2); // g.drawLine(x1,y1,x2,y2); } /* WLH 24 April 99 vx[nv] = x; vy[nv] = y; vz[nv] = z; nv++; vx[nv] = x1; vy[nv] = y1; vz[nv] = z; nv++; */ // System.out.println("line " + x + " " + y + "" + x1 + " " + y1); // g.drawLine(x,y,x1,y1); // lengthen the pole to accomodate the 50 knot barbs if (nbarb50 > 0) { d = d + 0.125f * scale; x1 = (x + x0 * d); y1 = (y + y0 * d); /* WLH 24 April 99 vx[nv] = x; vy[nv] = y; vz[nv] = z; nv++; vx[nv] = x1; vy[nv] = y1; vz[nv] = z; nv++; */ // System.out.println("line50 " + x + " " + y + "" + x1 + " " + y1); // g.drawLine(x,y,x1,y1); } // plot the 50 kt wind barbs /* WLH 5 Nov 99 s195 = (float) Math.sin(195 * Data.DEGREES_TO_RADIANS); c195 = (float) Math.cos(195 * Data.DEGREES_TO_RADIANS); */ for (int j = 0; j < nbarb50; j++) { x1 = (x + x0 * d); y1 = (y + y0 * d); d = d + 0.3f * scale; x3 = (x + x0 * d); y3 = (y + y0 * d); /* WLH 5 Nov 99 if (south) { x2 = (x3+barb*(x0*s195+y0*c195)); y2 = (y3-barb*(x0*c195-y0*s195)); } else { x2 = (x3-barb*(x0*s195+y0*c195)); y2 = (y3+barb*(x0*c195-y0*s195)); } */ if (south) { x2 = (x + x0 * (d + slant) - y0 * barb); y2 = (y + y0 * (d + slant) + x0 * barb); } else { x2 = (x + x0 * (d + slant) + y0 * barb); y2 = (y + y0 * (d + slant) - x0 * barb); } float[] xp = {x1, x2, x3}; float[] yp = {y1, y2, y3}; tx[nt] = x1; ty[nt] = y1; tz[nt] = z; nt++; tx[nt] = x2; ty[nt] = y2; tz[nt] = z; nt++; tx[nt] = x3; ty[nt] = y3; tz[nt] = z; nt++; /* System.out.println("barb50 " + x1 + " " + y1 + "" + x2 + " " + y2 + " " + x3 + " " + y3); */ // g.fillPolygon(xp,yp,3); // start location for the next barb x1 = x3; y1 = y3; } // grf 17 Nov 2003 change this to shorten the pole and print the speed if (noNumbers) { // WLH 24 April 99 - now plot the pole vx[nv] = x; vy[nv] = y; vz[nv] = z; nv++; vx[nv] = x1; vy[nv] = y1; vz[nv] = z; nv++; mbarb[2] = x1; mbarb[3] = y1; } else { // add numerical value to wind barbs // guess some factors to shorten the start of the pole float start_pole = 0.4f * scale; x1 = (x + x0 * start_pole); y1 = (y + y0 * start_pole); x2 = (x + x0 * d); y2 = (y + y0 * d); // draw the shaft vx[nv] = x1; vy[nv] = y1; vz[nv] = z; nv++; vx[nv] = x2; vy[nv] = y2; vz[nv] = z; nv++; mbarb[2] = x2; mbarb[3] = y2; // draw the speed to 1 dec place by default // Experimental factors in front of scale - get same as Swell NumberFormat nf = NumberFormat.getInstance(); nf.setMaximumFractionDigits(numDecPlaces); String speedString = nf.format((double) wnd_spd); // grf 2 Jun 2004 set z value the same as the barb double[] start = {x, y - 0.20 * scale, z}; double[] base = {0.375 * scale, 0.0, 0.0}; double up[] = {0.0, 0.375 * scale, 0.0}; VisADLineArray array = PlotText.render_label(speedString, start, base, up, true); int nl = array.vertexCount; int k = 0; for (int i = 0; i < nl; i++) { vx[nv] = array.coordinates[k++]; vy[nv] = array.coordinates[k++]; vz[nv] = array.coordinates[k++]; nv++; } } } else { // if (wnd_spd < 2.5) // wind < 2.5 kts. Plot a circle float rad = (0.7f * pt_size); // draw 8 segment circle, center = (x, y), radius = rad // 1st segment vx[nv] = x - rad; vy[nv] = y; vz[nv] = z; nv++; vx[nv] = x - 0.7f * rad; vy[nv] = y + 0.7f * rad; vz[nv] = z; nv++; // 2nd segment vx[nv] = x - 0.7f * rad; vy[nv] = y + 0.7f * rad; vz[nv] = z; nv++; vx[nv] = x; vy[nv] = y + rad; vz[nv] = z; nv++; // 3rd segment vx[nv] = x; vy[nv] = y + rad; vz[nv] = z; nv++; vx[nv] = x + 0.7f * rad; vy[nv] = y + 0.7f * rad; vz[nv] = z; nv++; // 4th segment vx[nv] = x + 0.7f * rad; vy[nv] = y + 0.7f * rad; vz[nv] = z; nv++; vx[nv] = x + rad; vy[nv] = y; vz[nv] = z; nv++; // 5th segment vx[nv] = x + rad; vy[nv] = y; vz[nv] = z; nv++; vx[nv] = x + 0.7f * rad; vy[nv] = y - 0.7f * rad; vz[nv] = z; nv++; // 6th segment vx[nv] = x + 0.7f * rad; vy[nv] = y - 0.7f * rad; vz[nv] = z; nv++; vx[nv] = x; vy[nv] = y - rad; vz[nv] = z; nv++; // 7th segment vx[nv] = x; vy[nv] = y - rad; vz[nv] = z; nv++; vx[nv] = x - 0.7f * rad; vy[nv] = y - 0.7f * rad; vz[nv] = z; nv++; // 8th segment vx[nv] = x - 0.7f * rad; vy[nv] = y - 0.7f * rad; vz[nv] = z; nv++; vx[nv] = x - rad; vy[nv] = y; vz[nv] = z; nv++; // System.out.println("circle " + x + " " + y + "" + rad); // g.drawOval(x-rad,y-rad,2*rad,2*rad); mbarb[2] = x; mbarb[3] = y; } numv[0] = nv; numt[0] = nt; return mbarb; }
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(); } }
/** test BarbManipulationRendererJ3D */ public static void main(String args[]) throws VisADException, RemoteException { System.out.println("BMR.main()"); // construct RealTypes for wind record components RealType lat = RealType.Latitude; RealType lon = RealType.Longitude; RealType windx = RealType.getRealType("windx", CommonUnit.meterPerSecond); RealType windy = RealType.getRealType("windy", CommonUnit.meterPerSecond); RealType red = RealType.getRealType("red"); RealType green = RealType.getRealType("green"); // EarthVectorType extends RealTupleType and says that its // components are vectors in m/s with components parallel // to Longitude (positive east) and Latitude (positive north) EarthVectorType windxy = new EarthVectorType(windx, windy); RealType wind_dir = RealType.getRealType("wind_dir", CommonUnit.degree); RealType wind_speed = RealType.getRealType("wind_speed", CommonUnit.meterPerSecond); RealTupleType windds = null; if (args.length > 0) { System.out.println("polar winds"); windds = new RealTupleType( new RealType[] {wind_dir, wind_speed}, new WindPolarCoordinateSystem(windxy), null); } // construct Java3D display and mappings that govern // how wind records are displayed DisplayImpl display = new DisplayImplJ3D("display1", new TwoDDisplayRendererJ3D()); ScalarMap lonmap = new ScalarMap(lon, Display.XAxis); display.addMap(lonmap); ScalarMap latmap = new ScalarMap(lat, Display.YAxis); display.addMap(latmap); FlowControl flow_control; if (args.length > 0) { ScalarMap winds_map = new ScalarMap(wind_speed, Display.Flow1Radial); display.addMap(winds_map); winds_map.setRange(0.0, 1.0); // do this for barb rendering ScalarMap windd_map = new ScalarMap(wind_dir, Display.Flow1Azimuth); display.addMap(windd_map); windd_map.setRange(0.0, 360.0); // do this for barb rendering flow_control = (FlowControl) windd_map.getControl(); flow_control.setFlowScale(0.15f); // this controls size of barbs } else { ScalarMap windx_map = new ScalarMap(windx, Display.Flow1X); display.addMap(windx_map); windx_map.setRange(-1.0, 1.0); // do this for barb rendering ScalarMap windy_map = new ScalarMap(windy, Display.Flow1Y); display.addMap(windy_map); windy_map.setRange(-1.0, 1.0); // do this for barb rendering flow_control = (FlowControl) windy_map.getControl(); flow_control.setFlowScale(0.15f); // this controls size of barbs } display.addMap(new ScalarMap(red, Display.Red)); display.addMap(new ScalarMap(green, Display.Green)); display.addMap(new ConstantMap(1.0, Display.Blue)); DataReferenceImpl[] refs = new DataReferenceImpl[N * N]; int k = 0; // create an array of N by N winds for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { double u = 2.0 * i / (N - 1.0) - 1.0; double v = 2.0 * j / (N - 1.0) - 1.0; // each wind record is a Tuple (lon, lat, (windx, windy), red, green) // set colors by wind components, just for grins Tuple tuple; double fx = 30.0 * u; double fy = 30.0 * v; if (args.length > 0) { double fd = Data.RADIANS_TO_DEGREES * Math.atan2(-fx, -fy); double fs = Math.sqrt(fx * fx + fy * fy); tuple = new Tuple( new Data[] { new Real(lon, 10.0 * u), new Real(lat, 10.0 * v - 40.0), new RealTuple(windds, new double[] {fd, fs}), new Real(red, u), new Real(green, v) }); } else { tuple = new Tuple( new Data[] { new Real(lon, 10.0 * u), new Real(lat, 10.0 * v - 40.0), new RealTuple(windxy, new double[] {fx, fy}), new Real(red, u), new Real(green, v) }); } // construct reference for wind record refs[k] = new DataReferenceImpl("ref_" + k); refs[k].setData(tuple); // link wind record to display via BarbManipulationRendererJ3D // so user can change barb by dragging it // drag with right mouse button and shift to change direction // drag with right mouse button and no shift to change speed BarbManipulationRendererJ3D renderer = new BarbManipulationRendererJ3D(); renderer.setKnotsConvert(true); display.addReferences(renderer, refs[k]); // link wind record to a CellImpl that will listen for changes // and print them WindGetterJ3D cell = new WindGetterJ3D(flow_control, refs[k]); cell.addReference(refs[k]); k++; } } // instead of linking the wind record "DataReferenceImpl refs" to // the WindGetterJ3Ds, you can have some user interface event (e.g., // the user clicks on "DONE") trigger code that does a getData() on // all the refs and stores the records in a file. // create JFrame (i.e., a window) for display and slider JFrame frame = new JFrame("test BarbManipulationRendererJ3D"); 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); }