//
// ShadowTypeJ3D.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.java3d;

import visad.*;

import javax.media.j3d.*;

import javax.vecmath.*;

import java.util.Vector;

import java.rmi.*;

/**
 * The ShadowTypeJ3D hierarchy shadows the MathType hierarchy, within a
 * DataDisplayLink, under Java3D.
 * 

*/ public abstract class ShadowTypeJ3D extends ShadowType { /** This holds the cached java3d Appearances */ private static java.util.Hashtable appearanceCache = new java.util.Hashtable(); /** This holds the cached java3d ColoringAttributes */ private static java.util.Hashtable coloringAttributesCache = new java.util.Hashtable(); /** This holds the cached java3d TransparencyAttributes */ private static java.util.Hashtable transparencyAttributesCache = new java.util.Hashtable(); /** Do we try to cache appearances */ private boolean cacheAppearances = false; /** * Do we try to merge Geometries into existings Shape3D scene graph components */ private boolean mergeShapes = false; /** For logging the number of Appearance objects created */ public static int appearanceCnt = 0; /** For logging the number of Shape3D objects created */ public static int shape3DCnt = 0; /** basic information about this ShadowTypeJ3D */ MathType Type; // MathType being shadowed /** */ transient DataDisplayLink Link; /** */ transient DisplayImplJ3D display; /** */ transient private Data data; // from Link.getData() /** */ private ShadowTypeJ3D Parent; // String and TextControl to pass on to children /** */ String inheritedText = null; /** */ TextControl inheritedTextControl = null; /** */ ShadowType adaptedShadowType; /** */ ProjectionControlListener projListener = null; /** * Create a new ShadowTypeJ3D * * @param type * MathType of the data * @param link * the data/display link * @param parent * parent ShadowType * * @throws RemoteException * problem creating remote instance * @throws VisADException * problem creating local instance */ public ShadowTypeJ3D(MathType type, DataDisplayLink link, ShadowType parent) throws VisADException, RemoteException { super(type, link, getAdaptedParent(parent)); Type = type; Link = link; display = (DisplayImplJ3D) link.getDisplay(); Parent = (ShadowTypeJ3D) parent; data = link.getData(); } /** * Get the adapted ShadowType for the parent * * @param parent * the parent object to test * * @return the adapted ShadowType */ public static ShadowType getAdaptedParent(ShadowType parent) { if (parent == null) return null; else return parent.getAdaptedShadowType(); } /** * Get the adapted ShadowType for this instance * * @return the adapted ShadowType */ public ShadowType getAdaptedShadowType() { return adaptedShadowType; } /** * * * @param type * @param doRef * * @return component array * * @throws VisADException */ public ShadowRealType[] getComponents(ShadowType type, boolean doRef) throws VisADException { return adaptedShadowType.getComponents(type, doRef); } /** * * * @return inherited text */ public String getParentText() { if (Parent != null && Parent.inheritedText != null && Parent.inheritedTextControl != null) { return Parent.inheritedText; } else { return null; } } /** * * * @return inherited text control */ public TextControl getParentTextControl() { if (Parent != null && Parent.inheritedText != null && Parent.inheritedTextControl != null) { return Parent.inheritedTextControl; } else { return null; } } /** * * * @param text * @param control */ public void setText(String text, TextControl control) { inheritedText = text; inheritedTextControl = control; } /** * Get the data * * @return the data */ public Data getData() { return data; } /** * Get the display * * @return the display */ public DisplayImpl getDisplay() { return display; } /** * Get the MathType of the Data * * @return the MathType */ public MathType getType() { return Type; } /** * Get the level of difficulty for this transform * * @return the level of difficulty */ public int getLevelOfDifficulty() { return adaptedShadowType.getLevelOfDifficulty(); } /** * * * @return boolean TBD */ public boolean getMultipleDisplayScalar() { return adaptedShadowType.getMultipleDisplayScalar(); } /** * * * @return boolean TBD */ public boolean getMappedDisplayScalar() { return adaptedShadowType.getMappedDisplayScalar(); } /** * * * @return int array display indices */ public int[] getDisplayIndices() { return adaptedShadowType.getDisplayIndices(); } /** * * * @return int array value indices */ public int[] getValueIndices() { return adaptedShadowType.getValueIndices(); } /** * checkIndices: check for rendering difficulty, etc * * @param indices * @param display_indices * @param value_indices * @param isTransform * @param levelOfDifficulty * * @return num occcurrences RealType and DisplayRealType * * @throws RemoteException * @throws VisADException */ public int checkIndices(int[] indices, int[] display_indices, int[] value_indices, boolean[] isTransform, int levelOfDifficulty) throws VisADException, RemoteException { return adaptedShadowType.checkIndices(indices, display_indices, value_indices, isTransform, levelOfDifficulty); } /** * clear AccumulationVector * * @throws VisADException */ public void preProcess() throws VisADException { } /** * transform data into a Java3D scene graph; add generated scene graph * components as children of group; value_array are inherited valueArray * values; default_values are defaults for each display.DisplayRealTypeVector; * return true if need post-process; this is default (for ShadowTextType) * * @param group * group to add to * @param data * the data to transform * @param value_array * the values * @param default_values * the default values * @param renderer * the renderer * * @return false * * @throws RemoteException * @throws VisADException */ public boolean doTransform(Object group, Data data, float[] value_array, float[] default_values, DataRenderer renderer) throws VisADException, RemoteException { return false; } /** * render accumulated Vector of value_array-s to and add to group; then clear * AccumulationVector * * @param group * * @throws VisADException */ public void postProcess(Object group) throws VisADException { } /* helpers for doTransform */ /** * map values into display_values according to ScalarMap-s in reals * * @param display_values * @param values * @param reals * * @throws VisADException */ public static void mapValues(float[][] display_values, double[][] values, ShadowRealType[] reals) throws VisADException { ShadowType.mapValues(display_values, values, reals); } /** * map values into display_values according to ScalarMap-s in reals * * @param display_values * @param values * @param reals * * @throws VisADException */ public static void mapValues(float[][] display_values, float[][] values, ShadowRealType[] reals) throws VisADException { mapValues(display_values, values, reals, true); } /** * map values into display_values according to ScalarMap-s in reals * * @param display_values * @param values * @param reals * @param copy * * @throws VisADException */ public static void mapValues(float[][] display_values, float[][] values, ShadowRealType[] reals, boolean copy) throws VisADException { ShadowType.mapValues(display_values, values, reals, copy); } /** * * * @param spatial_values * @param color_values * * @return point geometry array * * @throws VisADException */ public static VisADGeometryArray makePointGeometry(float[][] spatial_values, byte[][] color_values) throws VisADException { return ShadowType.makePointGeometry(spatial_values, color_values); } /** * Make an Appearance object for this display * * @param mode * GraphicsModeControl * @param constant_alpha * the constant alpha value * @param constant_color * the constant color value * @param geometry * the GeometryArray * @param no_material * flag for material * * @return appearance object constructed from geometry array */ public Appearance makeAppearance(GraphicsModeControl mode, TransparencyAttributes constant_alpha, ColoringAttributes constant_color, GeometryArray geometry, boolean no_material) { return ShadowTypeJ3D.staticMakeCachedAppearance(mode, constant_alpha, constant_color, geometry, no_material, false); } /** * Make an Appearance that may be cached or not, depending on the okToCache * and the cache flag * * @param mode * GraphicsModeControl * @param constant_alpha * the constant alpha value * @param constant_color * the constant color value * @param geometry * the GeometryArray * @param no_material * flag for material * @param okToCache * flag for caching checked with mode.getCacheAppearances * * @return appearance object constructed from geometry array */ private Appearance makeCachedAppearance(GraphicsModeControl mode, TransparencyAttributes constant_alpha, ColoringAttributes constant_color, GeometryArray geometry, boolean no_material, boolean okToCache) { return ShadowTypeJ3D.staticMakeCachedAppearance(mode, constant_alpha, constant_color, geometry, no_material, okToCache); } /** * A utility method to add the given geometry into the given group with the * given appearance. If the mergeShapes flag is true then this will look for * an existing child Shape3D node of the group that has the same Appearance * and contains geometries of the same type. If found it will add the geometry * to that Shape3D node. If not found or if mergeShapes is false then this * behaves normally, creating a new Shape3D node and adding it to the group. * * @param group * group to add to * @param geometry * geometry to add * @param appearance * appearance */ private void addToShape(Group group, GeometryArray geometry, Appearance appearance) { Shape3D shape = null; if (mergeShapes) { int cnt = group.numChildren(); for (int i = 0; i < cnt; i++) { Node node = group.getChild(i); if (!(node instanceof Shape3D)) continue; Shape3D s = (Shape3D) node; // Make sure the geometries are the same int subcnt = s.numGeometries(); if (subcnt > 0) { if (!(s.getGeometry(0).getClass().equals(geometry.getClass()))) { continue; } } // Make sure the appearance is the same if (s.getAppearance().equals(appearance)) { shape = s; break; } } } if (shape == null) { shape = new Shape3D(geometry, appearance); shape.setCapability(Shape3D.ALLOW_GEOMETRY_READ); shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ); group.addChild(shape); shape3DCnt++; } else { shape.addGeometry(geometry); } } /** * A utility method to create a ColoringAttribute with the given colors If the * cacheAppearances flag is true then this will try to find the * ColoringAttribute in the cache. If false it just creates a new one. Note: * If caching is on then the result object should be treated as being * immutable * * @param red * red value * @param green * green value * @param blue * blue value * * @return the ColoringAttributes */ private ColoringAttributes getColoringAttributes(float red, float green, float blue) { ColoringAttributes ca = null; String key = null; if (cacheAppearances) { key = red + "," + green + "," + blue; ca = (ColoringAttributes) coloringAttributesCache.get(key); } if (ca == null) { ca = new ColoringAttributes(red, green, blue, ColoringAttributes.SHADE_GOURAUD); ca.setCapability(ColoringAttributes.ALLOW_COLOR_READ); ca.setCapability(ColoringAttributes.ALLOW_SHADE_MODEL_READ); if (cacheAppearances) { coloringAttributesCache.put(key, ca); } } return ca; } /** * A utility method to create a TransparencyAttributes with the given mode and * value. If the flag cacheAppearances is true then this will try to find the * TransparencyAttributes in the cache. If false it just creates a new one. * Note: If caching is on then the result object should be treated as being * immutable * * @param mode * Transparency mode * @param value * transparancy value * * @return cached or new TransparencyAttributes object */ private TransparencyAttributes getTransparencyAttributes(int mode, float value) { String key = null; TransparencyAttributes ta = null; if (cacheAppearances) { key = mode + "_" + value; ta = (TransparencyAttributes) transparencyAttributesCache.get(key); } if (ta == null) { ta = new TransparencyAttributes(mode, value); ta.setCapability(TransparencyAttributes.ALLOW_MODE_READ); ta.setCapability(TransparencyAttributes.ALLOW_VALUE_READ); if (cacheAppearances) { transparencyAttributesCache.put(key, ta); } } return ta; } /** * Construct an Appearance object from a GeometryArray * * @param mode * GraphicsModeControl * @param constant_alpha * transparency attributes * @param constant_color * color to use * @param geometry * geometry to use for the appearance * @param no_material * true to not use a Material for illumination, false to use it for * 2-D geometries * * @return The new appearance */ public static Appearance staticMakeAppearance(GraphicsModeControl mode, TransparencyAttributes constant_alpha, ColoringAttributes constant_color, GeometryArray geometry, boolean no_material) { return staticMakeCachedAppearance(mode, constant_alpha, constant_color, geometry, no_material, false); } /** * Construct an Appearance object from a GeometryArray * * @param mode * GraphicsModeControl * @param constant_alpha * transparency attributes * @param constant_color * color to use * @param geometry * geometry to use for the appearance * @param no_material * true to not use a Material for illumination, false to use it for * 2-D geometries * @param okToCache * If true and if the mode's cacheAppearances flag is true then we * will use the appearance cache. * * @return The new appearance or, if available a previously cached one */ private static Appearance staticMakeCachedAppearance( GraphicsModeControl mode, TransparencyAttributes constant_alpha, ColoringAttributes constant_color, GeometryArray geometry, boolean no_material, boolean okToCache) { boolean doMaterial = false; if (!(geometry instanceof LineArray || geometry instanceof PointArray || geometry instanceof IndexedLineArray || geometry instanceof IndexedPointArray || geometry instanceof IndexedLineStripArray || geometry instanceof LineStripArray)) { if (!no_material) { doMaterial = true; } } Object cacheKey = null; Appearance appearance = null; if (mode.getCacheAppearances() && okToCache) { cacheKey = mode.getSaveString() + "_" + (constant_alpha==null?"null" :(constant_alpha.getTransparency()+"_" + constant_alpha.getTransparencyMode())) + "_" + constant_color + "_" + new Boolean(doMaterial); appearance = (Appearance) appearanceCache.get(cacheKey); if (appearance != null) { return appearance; } } appearanceCnt++; appearance = new Appearance(); appearance.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_READ); appearance.setCapability(Appearance.ALLOW_LINE_ATTRIBUTES_READ); appearance.setCapability(Appearance.ALLOW_MATERIAL_READ); appearance.setCapability(Appearance.ALLOW_POINT_ATTRIBUTES_READ); appearance.setCapability(Appearance.ALLOW_POLYGON_ATTRIBUTES_READ); appearance.setCapability(Appearance.ALLOW_RENDERING_ATTRIBUTES_READ); appearance.setCapability(Appearance.ALLOW_TEXGEN_READ); appearance.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ); appearance.setCapability(Appearance.ALLOW_TEXTURE_READ); /* TDR (2013-10-16): Can possibly cause problems on ATI graphics appearance.setCapability(Appearance.ALLOW_RENDERING_ATTRIBUTES_WRITE); */ // appearance.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_READ); appearance.setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_READ); LineAttributes line = new LineAttributes(); line.setCapability(LineAttributes.ALLOW_ANTIALIASING_READ); line.setCapability(LineAttributes.ALLOW_PATTERN_READ); line.setCapability(LineAttributes.ALLOW_WIDTH_READ); line.setLineWidth(mode.getLineWidth()); int pattern = GraphicsModeControlJ3D.LINE_PATTERN[mode.getLineStyle()]; line.setLinePattern(pattern); appearance.setLineAttributes(line); PointAttributes point = new PointAttributes(); point.setCapability(PointAttributes.ALLOW_ANTIALIASING_READ); point.setCapability(PointAttributes.ALLOW_SIZE_READ); point.setPointSize(mode.getPointSize()); appearance.setPointAttributes(point); PolygonAttributes polygon = new PolygonAttributes(); polygon.setCapability(PolygonAttributes.ALLOW_CULL_FACE_READ); polygon.setCapability(PolygonAttributes.ALLOW_MODE_READ); polygon.setCapability(PolygonAttributes.ALLOW_NORMAL_FLIP_READ); polygon.setCapability(PolygonAttributes.ALLOW_OFFSET_READ); polygon.setCullFace(PolygonAttributes.CULL_NONE); polygon.setPolygonMode(mode.getPolygonMode()); try { float polygonOffset = mode.getPolygonOffset(); if (polygonOffset == polygonOffset) polygon.setPolygonOffset(polygonOffset); } catch (Exception e) { } // - TDR, use reflection since setPolygonOffsetFactor is not available in // earlier versions of Java3D. try { java.lang.reflect.Method method = polygon.getClass().getMethod( "setPolygonOffsetFactor", new Class[] { float.class }); float polygonOffsetFactor = mode.getPolygonOffsetFactor(); if (polygonOffsetFactor == polygonOffsetFactor) { method.invoke(polygon, new Object[] {polygonOffsetFactor}); } } catch (Exception e) { } appearance.setPolygonAttributes(polygon); RenderingAttributes rendering = new RenderingAttributes(); rendering.setCapability(RenderingAttributes.ALLOW_ALPHA_TEST_FUNCTION_READ); rendering.setCapability(RenderingAttributes.ALLOW_ALPHA_TEST_VALUE_READ); rendering.setCapability(RenderingAttributes.ALLOW_DEPTH_ENABLE_READ); /* TDR (2013-10-16): Can possibly cause problems on ATI graphics rendering.setCapability (RenderingAttributes.ALLOW_VISIBLE_WRITE); */ //rendering.setCapability(RenderingAttributes.ALLOW_IGNORE_VERTEX_COLORS_READ // ); // rendering.setCapability(RenderingAttributes.ALLOW_RASTER_OP_READ); // rendering.setCapability(RenderingAttributes.ALLOW_VISIBLE_READ); rendering.setDepthBufferEnable(((GraphicsModeControlJ3D)mode).getDepthBufferEnable()); appearance.setRenderingAttributes(rendering); if (constant_color != null) { // constant_color.setCapability(ColoringAttributes.ALLOW_COLOR_READ); //constant_color.setCapability(ColoringAttributes.ALLOW_SHADE_MODEL_READ); appearance.setColoringAttributes(constant_color); } // only do Material if geometry is 2-D (not 0-D points or 1-D lines) if (doMaterial) { Material material = new Material(); material.setCapability(Material.ALLOW_COMPONENT_READ); material.setSpecularColor(0.0f, 0.0f, 0.0f); // no lighting in 2-D mode if (!mode.getMode2D()) material.setLightingEnable(true); appearance.setMaterial(material); } if (constant_alpha != null) { // constant_alpha.setCapability(TransparencyAttributes. // ALLOW_BLEND_FUNCTION_READ); // constant_alpha.setCapability(TransparencyAttributes.ALLOW_MODE_READ); // constant_alpha.setCapability(TransparencyAttributes.ALLOW_VALUE_READ); appearance.setTransparencyAttributes(constant_alpha); } if (cacheKey != null) { appearanceCache.put((Object) cacheKey, appearance); } return appearance; } /* * public static Appearance staticMakeAppearance(GraphicsModeControl mode, * TransparencyAttributes constant_alpha, ColoringAttributes constant_color, * GeometryArray geometry, boolean no_material) { Appearance appearance = new * Appearance(); * appearance.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_READ); * appearance.setCapability(Appearance.ALLOW_LINE_ATTRIBUTES_READ); * appearance.setCapability(Appearance.ALLOW_MATERIAL_READ); * appearance.setCapability(Appearance.ALLOW_POINT_ATTRIBUTES_READ); * appearance.setCapability(Appearance.ALLOW_POLYGON_ATTRIBUTES_READ); * appearance.setCapability(Appearance.ALLOW_RENDERING_ATTRIBUTES_READ); * appearance.setCapability(Appearance.ALLOW_TEXGEN_READ); * appearance.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ); * appearance.setCapability(Appearance.ALLOW_TEXTURE_READ); * appearance.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_READ); * appearance.setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_READ); * * LineAttributes line = new LineAttributes(); * line.setLineWidth(mode.getLineWidth()); int pattern = * GraphicsModeControlJ3D.LINE_PATTERN[mode.getLineStyle()]; * line.setLinePattern(pattern); appearance.setLineAttributes(line); * * PointAttributes point = new PointAttributes(); * point.setPointSize(mode.getPointSize()); * appearance.setPointAttributes(point); * * PolygonAttributes polygon = new PolygonAttributes(); * polygon.setCullFace(PolygonAttributes.CULL_NONE); * polygon.setPolygonMode(mode.getPolygonMode()); * * try { float polygonOffset = mode.getPolygonOffset(); if (polygonOffset == * polygonOffset) polygon.setPolygonOffset(polygonOffset); } catch (Exception * e) { } * * appearance.setPolygonAttributes(polygon); * * RenderingAttributes rendering = new RenderingAttributes(); * rendering.setDepthBufferEnable(true); * appearance.setRenderingAttributes(rendering); * * if (constant_color != null) { * appearance.setColoringAttributes(constant_color); } // only do Material if * geometry is 2-D (not 0-D points or 1-D lines) if (!(geometry instanceof * LineArray || geometry instanceof PointArray || geometry instanceof * IndexedLineArray || geometry instanceof IndexedPointArray || geometry * instanceof IndexedLineStripArray || geometry instanceof LineStripArray)) { * if (!no_material) { Material material = new Material(); * material.setSpecularColor(0.0f, 0.0f, 0.0f); // no lighting in 2-D mode if * (!mode.getMode2D()) material.setLightingEnable(true); * appearance.setMaterial(material); //TEST * appearance.setCapability(Appearance.ALLOW_MATERIAL_READ); } if * (constant_alpha != null) { * appearance.setTransparencyAttributes(constant_alpha); } } * * return appearance; } */ /** * collect and transform Shape DisplayRealType values from display_values; * offset by spatial_values, selected by range_select * * @param display_values * @param valueArrayLength * @param valueToMap * @param MapVector * @param valueToScalar * @param display * @param default_values * @param inherited_values * @param spatial_values * @param color_values * @param range_select * @param index * @param shadow_api * * @return transformed Shape values * * @throws RemoteException * @throws VisADException */ public VisADGeometryArray[] assembleShape(float[][] display_values, int valueArrayLength, int[] valueToMap, Vector MapVector, int[] valueToScalar, DisplayImpl display, float[] default_values, int[] inherited_values, float[][] spatial_values, byte[][] color_values, boolean[][] range_select, int index, ShadowType shadow_api) throws VisADException, RemoteException { return adaptedShadowType.assembleShape(display_values, valueArrayLength, valueToMap, MapVector, valueToScalar, display, default_values, inherited_values, spatial_values, color_values, range_select, index, shadow_api); } /** * collect and transform spatial DisplayRealType values from display_values; * add spatial offset DisplayRealType values; adjust flow1_values and * flow2_values for any coordinate transform; if needed, return a spatial Set * from spatial_values, with the same topology as domain_set (or an * appropriate Irregular topology); domain_set = null and allSpatial = false * if not called from ShadowFunctionType * * @param spatial_values * @param display_values * @param valueArrayLength * @param valueToScalar * @param display * @param default_values * @param inherited_values * @param domain_set * @param allSpatial * @param set_for_shape * @param spatialDimensions * @param range_select * @param flow1_values * @param flow2_values * @param flowScale * @param swap * @param renderer * @param shadow_api * * @return spatial Set from spatial values * * @throws RemoteException * @throws VisADException */ public Set assembleSpatial(float[][] spatial_values, float[][] display_values, int valueArrayLength, int[] valueToScalar, DisplayImpl display, float[] default_values, int[] inherited_values, Set domain_set, boolean allSpatial, boolean set_for_shape, int[] spatialDimensions, boolean[][] range_select, float[][] flow1_values, float[][] flow2_values, float[] flowScale, boolean[] swap, DataRenderer renderer, ShadowType shadow_api) throws VisADException, RemoteException { return adaptedShadowType.assembleSpatial(spatial_values, display_values, valueArrayLength, valueToScalar, display, default_values, inherited_values, domain_set, allSpatial, set_for_shape, spatialDimensions, range_select, flow1_values, flow2_values, flowScale, swap, renderer, shadow_api); } /** * assemble Flow components; Flow components are 'single', so no compositing * is required * * @param flow1_values * @param flow2_values * @param flowScale * @param display_values * @param valueArrayLength * @param valueToScalar * @param display * @param default_values * @param range_select * @param renderer * @param shadow_api * * @throws RemoteException * @throws VisADException */ public void assembleFlow(float[][] flow1_values, float[][] flow2_values, float[] flowScale, float[] arrowScale, float[][] display_values, int valueArrayLength, int[] valueToScalar, DisplayImpl display, float[] default_values, boolean[][] range_select, DataRenderer renderer, ShadowType shadow_api) throws VisADException, RemoteException { adaptedShadowType.assembleFlow(flow1_values, flow2_values, flowScale, arrowScale, display_values, valueArrayLength, valueToScalar, display, default_values, range_select, renderer, shadow_api); } /** * * * @param which * @param flow_values * @param flowScale * @param spatial_values * @param color_values * @param range_select * * @return flow geometry array * * @throws VisADException */ public VisADGeometryArray[] makeFlow(int which, float[][] flow_values, float flowScale, float arrowScale, float[][] spatial_values, byte[][] color_values, boolean[][] range_select) throws VisADException { return adaptedShadowType.makeFlow(which, flow_values, flowScale, arrowScale, spatial_values, color_values, range_select); } /** * * * @param which * @param flow_values * @param flowScale * @param spatial_values * @param spatial_set * @param spatialManifoldDimension * @param color_values * @param range_select * @param valueArrayLength * @param valueToMap * @param MapVector * * @return streamline geometry array * * @throws VisADException */ public VisADGeometryArray[] makeStreamline(int which, float[][] flow_values, float flowScale, float[][] spatial_values, Set spatial_set, int spatialManifoldDimension, byte[][] color_values, boolean[][] range_select, int valueArrayLength, int[] valueToMap, Vector MapVector) throws VisADException { return adaptedShadowType.makeStreamline(which, flow_values, flowScale, spatial_values, spatial_set, spatialManifoldDimension, color_values, range_select, valueArrayLength, valueToMap, MapVector); } /** * * * @param valueArrayLength * @param valueToScalar * @param display_values * @param inherited_values * @param MapVector * @param valueToMap * @param domain_length * @param range_select * @param spatialManifoldDimension * @param spatial_set * @param color_values * @param indexed * @param group * @param mode * @param swap * @param constant_alpha * @param constant_color * @param shadow_api * @param Domain * @param DomainReferenceComponents * @param domain_set * @param domain_units * @param dataCoordinateSystem * * @return true if any contours created * * @throws VisADException */ public boolean makeContour(int valueArrayLength, int[] valueToScalar, float[][] display_values, int[] inherited_values, Vector MapVector, int[] valueToMap, int domain_length, boolean[][] range_select, int spatialManifoldDimension, Set spatial_set, byte[][] color_values, boolean indexed, Object group, GraphicsModeControl mode, boolean[] swap, float constant_alpha, float[] constant_color, ShadowType shadow_api, ShadowRealTupleType Domain, ShadowRealType[] DomainReferenceComponents, Set domain_set, Unit[] domain_units, CoordinateSystem dataCoordinateSystem) throws VisADException { return adaptedShadowType.makeContour(valueArrayLength, valueToScalar, display_values, inherited_values, MapVector, valueToMap, domain_length, range_select, spatialManifoldDimension, spatial_set, color_values, indexed, group, mode, swap, constant_alpha, constant_color, shadow_api, Domain, DomainReferenceComponents, domain_set, domain_units, dataCoordinateSystem); } private Object MUTEX = new Object(); public void addLabelsToGroup(Object group, VisADGeometryArray[] arrays, GraphicsModeControl mode, ContourControl control, ProjectionControl p_cntrl, int[] cnt_a, float constant_alpha, float[] constant_color) throws VisADException { //Make this thread safe synchronized(MUTEX) { int cnt = cnt_a[0]; if (cnt == 0) { projListener = new ProjectionControlListener(p_cntrl, control); } int n_labels = arrays.length; // add the stretchy line segments if we are not filling if (!control.contourFilled() && arrays != null) { projListener.LT_array[cnt] = new LabelTransform[3][n_labels]; GraphicsModeControl styledMode = (GraphicsModeControl) mode.clone(); styledMode.setLineStyle(control.getDashedStyle(), false); for (int ii = 0; ii < n_labels; ii++) { ContourLabelGeometry array = (ContourLabelGeometry) arrays[ii]; TransformGroup segL_trans_group = new TransformGroup(); TransformGroup segR_trans_group = new TransformGroup(); segL_trans_group.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); segL_trans_group.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); segL_trans_group.setCapability(TransformGroup.ALLOW_CHILDREN_READ); segR_trans_group.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); segR_trans_group.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); segR_trans_group.setCapability(TransformGroup.ALLOW_CHILDREN_READ); if (control.getAutoSizeLabels()) { LabelTransform lbl_trans = new LabelTransform(segL_trans_group, p_cntrl, new VisADGeometryArray[] { array.expSegLeft, array.segLeftAnchor }, array.segLeftScaleInfo, 1); projListener.LT_array[cnt][1][ii] = lbl_trans; lbl_trans = new LabelTransform(segR_trans_group, p_cntrl, new VisADGeometryArray[] { array.expSegRight, array.segRightAnchor }, array.segRightScaleInfo, 1); projListener.LT_array[cnt][2][ii] = lbl_trans; } ((Group) group).addChild(segL_trans_group); ((Group) group).addChild(segR_trans_group); if (array.isStyled) { addToGroup(segL_trans_group, array.expSegLeft, styledMode, constant_alpha, constant_color); addToGroup(segR_trans_group, array.expSegRight, styledMode, constant_alpha, constant_color); } else { addToGroup(segL_trans_group, array.expSegLeft, mode, constant_alpha, constant_color); addToGroup(segR_trans_group, array.expSegRight, mode, constant_alpha, constant_color); } } } else { projListener.LT_array[cnt] = new LabelTransform[1][n_labels]; } cnt = cnt_a[0]; for (int ii = 0; ii < n_labels; ii++) { TransformGroup lbl_trans_group = new TransformGroup(); lbl_trans_group.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); lbl_trans_group.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); lbl_trans_group.setCapability(TransformGroup.ALLOW_CHILDREN_READ); ContourLabelGeometry array = (ContourLabelGeometry) arrays[ii]; if (control.getAutoSizeLabels()) { LabelTransform lbl_trans = new LabelTransform(lbl_trans_group, p_cntrl, new VisADGeometryArray[] { array.label, array.labelAnchor }, null, 0); projListener.LT_array[cnt][0][ii] = lbl_trans; } ((Group) group).addChild(lbl_trans_group); addToGroup(lbl_trans_group, array.label, mode, constant_alpha, constant_color); } cnt++; projListener.cnt = cnt; cnt_a[0] = cnt; } } /** * * * @param text_values * @param text_control * @param spatial_values * @param color_values * @param range_select * * @return text geometry array * * @throws VisADException */ public VisADGeometryArray makeText(String[] text_values, TextControl text_control, float[][] spatial_values, byte[][] color_values, boolean[][] range_select) throws VisADException { return adaptedShadowType.makeText(text_values, text_control, spatial_values, color_values, range_select); } /** * composite and transform color and Alpha DisplayRealType values from * display_values, and return as (Red, Green, Blue, Alpha) * * @param display_values * @param valueArrayLength * @param valueToScalar * @param display * @param default_values * @param range_select * @param single_missing * @param shadow_api * * @return byte color array * * @throws RemoteException * @throws VisADException */ public byte[][] assembleColor(float[][] display_values, int valueArrayLength, int[] valueToScalar, DisplayImpl display, float[] default_values, boolean[][] range_select, boolean[] single_missing, ShadowType shadow_api) throws VisADException, RemoteException { return adaptedShadowType.assembleColor(display_values, valueArrayLength, valueToScalar, display, default_values, range_select, single_missing, shadow_api); } /** * return a composite of SelectRange DisplayRealType values from * display_values, as 0.0 for select and Double.Nan for no select (these * values can be added to other DisplayRealType values) * * @param display_values * @param domain_length * @param valueArrayLength * @param valueToScalar * @param display * @param shadow_api * * @return array of booleans as described above * * @throws VisADException */ public boolean[][] assembleSelect(float[][] display_values, int domain_length, int valueArrayLength, int[] valueToScalar, DisplayImpl display, ShadowType shadow_api) throws VisADException { return adaptedShadowType.assembleSelect(display_values, domain_length, valueArrayLength, valueToScalar, display, shadow_api); } /** * * * @param group * @param display_values * @param text_value * @param text_control * @param valueArrayLength * @param valueToScalar * @param default_values * @param inherited_values * @param renderer * * @return true if post-processing needed * * @throws RemoteException * @throws VisADException */ public boolean terminalTupleOrScalar(Object group, float[][] display_values, String text_value, TextControl text_control, int valueArrayLength, int[] valueToScalar, float[] default_values, int[] inherited_values, DataRenderer renderer) throws VisADException, RemoteException { boolean post = adaptedShadowType.terminalTupleOrScalar(group, display_values, text_value, text_control, valueArrayLength, valueToScalar, default_values, inherited_values, renderer, this); ensureNotEmpty(group); return post; } /** * this is a work-around for the NullPointerException at * javax.media.j3d.Shape3DRetained.setLive(Shape3DRetained.java:448) * * @param obj */ public void ensureNotEmpty(Object obj) { ensureNotEmpty(obj, display); } /** * * * @param obj * @param display */ public static void ensureNotEmpty(Object obj, DisplayImpl display) { if (!(obj instanceof Group)) return; Group group = (Group) obj; if (group.numChildren() > 0) return; GeometryArray geometry = new PointArray(1, GeometryArray.COORDINATES | GeometryArray.COLOR_3); geometry.setCapability(GeometryArray.ALLOW_COLOR_READ); geometry.setCapability(GeometryArray.ALLOW_COORDINATE_READ); geometry.setCapability(GeometryArray.ALLOW_COUNT_READ); geometry.setCapability(GeometryArray.ALLOW_FORMAT_READ); geometry.setCapability(GeometryArray.ALLOW_NORMAL_READ); // geometry.setCapability(GeometryArray.ALLOW_REF_DATA_READ); float[] coordinates = new float[3]; coordinates[0] = 1000000.0f; coordinates[1] = 1000000.0f; coordinates[2] = 1000000.0f; geometry.setCoordinates(0, coordinates); float[] colors = new float[3]; colors[0] = 0.0f; colors[1] = 0.0f; colors[2] = 0.0f; geometry.setColors(0, colors); Appearance appearance = staticMakeCachedAppearance(display .getGraphicsModeControl(), null, null, geometry, false, true); Shape3D shape = new Shape3D(geometry, appearance); shape.setCapability(Shape3D.ALLOW_GEOMETRY_READ); shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ); group.addChild(shape); } /** * Add the GeometryArray to the group * * * @param group * Group * @param array * array to add * @param mode * GraphicsModeControl * @param constant_alpha * constant alpha value * @param constant_color * constant color value * * @return true if successful * * @throws VisADException * unable to add the array to the group */ public boolean addToGroup(Object group, VisADGeometryArray array, GraphicsModeControl mode, float constant_alpha, float[] constant_color) throws VisADException { cacheAppearances = mode.getCacheAppearances(); mergeShapes = mode.getMergeGeometries(); if (array != null && array.vertexCount > 0) { float af = 0.0f; TransparencyAttributes c_alpha = null; if (constant_alpha == 1.0f) { // constant opaque alpha = NONE c_alpha = getTransparencyAttributes(TransparencyAttributes.NONE, 0.0f); } else if (constant_alpha == constant_alpha) { c_alpha = getTransparencyAttributes(mode.getTransparencyMode(), constant_alpha); af = constant_alpha; } else { // WLH - 18 Aug 99 - how could this have gone undetected for so long? // c_alpha = c_alpha = (mode.getTransparencyMode(), // 0.0f); c_alpha = getTransparencyAttributes(mode.getTransparencyMode(), 0.0f); } ColoringAttributes c_color = null; if (constant_color != null && constant_color.length == 3) { // c_color = new ColoringAttributes(); // c_color.setColor(constant_color[0], constant_color[1], // constant_color[2]); c_color = getColoringAttributes(constant_color[0], constant_color[1], constant_color[2]); // WLH 16 Oct 2001 if (!(array instanceof VisADLineArray || array instanceof VisADPointArray || array instanceof VisADLineStripArray) && array.colors == null) { int color_len = 3; if (af != 0.0f) { color_len = 4; } byte r = ShadowType.floatToByte(constant_color[0]); byte g = ShadowType.floatToByte(constant_color[1]); byte b = ShadowType.floatToByte(constant_color[2]); int len = array.vertexCount * color_len; byte[] colors = new byte[len]; int k = 0; if (color_len == 3) { for (int i = 0; i < len; i += 3) { colors[i] = r; colors[i + 1] = g; colors[i + 2] = b; } } else { byte a = ShadowType.floatToByte(af); for (int i = 0; i < len; i += 4) { colors[i] = r; colors[i + 1] = g; colors[i + 2] = b; colors[i + 3] = a; } } array.colors = colors; } } // MEM - for coordinates if mode2d GeometryArray geometry = display.makeGeometry(array); Appearance appearance = makeCachedAppearance(mode, c_alpha, c_color, geometry, false, true); addToShape((Group) group, geometry, appearance); // Shape3D shape = new Shape3D(geometry, appearance); // shape.setCapability(Shape3D.ALLOW_GEOMETRY_READ); // shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ); // ((Group) group).addChild(shape); return true; } else { return false; } } /** * Convenience method that returns a Branch node, which may be parented, * and whose only child can be detached. Acts also as an id since its parent * may have multiple children. */ public BranchGroup addToDetachableGroup(Object group, VisADGeometryArray array, GraphicsModeControl mode, float constant_alpha, float[] constant_color) throws VisADException { BranchGroup branch = (BranchGroup) makeBranch(); branch.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND); branch.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE); /* For example, this branch is detached from 'branch' during auto resizing. * New resized trcrArray is then added back to 'branch' */ BranchGroup trcrBranch = (BranchGroup) makeBranch(); addToGroup(trcrBranch, array, mode, constant_alpha, constant_color); branch.addChild(trcrBranch); ((BranchGroup)group).addChild(branch); return branch; } /** * * * @param group * @param array * @param mode * @param constant_alpha * @param constant_color * * @return true if added * * @throws VisADException */ public boolean addTextToGroup(Object group, VisADGeometryArray array, GraphicsModeControl mode, float constant_alpha, float[] constant_color) throws VisADException { if (array != null && array.vertexCount > 0) { float af = 0.0f; TransparencyAttributes c_alpha = null; if (constant_alpha == 1.0f) { // constant opaque alpha = NONE c_alpha = getTransparencyAttributes(TransparencyAttributes.NONE, 0.0f); } else if (constant_alpha == constant_alpha) { c_alpha = getTransparencyAttributes(mode.getTransparencyMode(), constant_alpha); af = constant_alpha; } else { // WLH - 18 Aug 99 - how could this have gone undetected for so long? // c_alpha = getTransparencyAttributes(mode.getTransparencyMode(), // 1.0f); c_alpha = getTransparencyAttributes(mode.getTransparencyMode(), 0.0f); } ColoringAttributes c_color = null; if (constant_color != null && constant_color.length == 3) { c_color = getColoringAttributes(constant_color[0], constant_color[1], constant_color[2]); // WLH 16 Oct 2001 (really 10 Dec 2001) if (!(array instanceof VisADLineArray || array instanceof VisADPointArray || array instanceof VisADLineStripArray) && array.colors == null) { int color_len = 3; if (af != 0.0f) { color_len = 4; } byte r = ShadowType.floatToByte(constant_color[0]); byte g = ShadowType.floatToByte(constant_color[1]); byte b = ShadowType.floatToByte(constant_color[2]); int len = array.vertexCount * color_len; byte[] colors = new byte[len]; if (color_len == 3) { for (int i = 0; i < len; i += 3) { colors[i] = r; colors[i + 1] = g; colors[i + 2] = b; } } else { byte a = ShadowType.floatToByte(af); for (int i = 0; i < len; i += 4) { colors[i] = r; colors[i + 1] = g; colors[i + 2] = b; colors[i + 3] = a; } } array.colors = colors; } } // MEM - for coordinates if mode2d GeometryArray geometry = display.makeGeometry(array); Appearance appearance = makeCachedAppearance(mode, c_alpha, c_color, geometry, false, true); Shape3D shape = new Shape3D(geometry, appearance); shape.setCapability(Shape3D.ALLOW_GEOMETRY_READ); shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ); ((Group) group).addChild(shape); if (array instanceof VisADTriangleArray) { GeometryArray geometry2 = display.makeGeometry(array); // Don't cache the appearance Appearance appearance2 = makeCachedAppearance(mode, c_alpha, c_color, geometry2, false, false); // LineAttributes la = appearance2.getLineAttributes(); // better without anti-aliasing // la.setLineAntialiasingEnable(true); PolygonAttributes pa = appearance2.getPolygonAttributes(); pa.setPolygonMode(PolygonAttributes.POLYGON_LINE); Shape3D shape2 = new Shape3D(geometry2, appearance2); shape2.setCapability(Shape3D.ALLOW_GEOMETRY_READ); shape2.setCapability(Shape3D.ALLOW_APPEARANCE_READ); ((Group) group).addChild(shape2); } return true; } else { return false; } } /** * Do we allo constant color surfaces? * * @return false */ public boolean allowConstantColorSurfaces() { return false; } /** * Get a String representation of this object * * @return the String representation of this object */ public String toString() { return adaptedShadowType.toString(); } } /** * Class ProjectionControlListener */ class ProjectionControlListener implements ControlListener { /** */ LabelTransform[][][] LT_array = null; /** */ ProjectionControl p_cntrl = null; /** */ ContourControl c_cntrl = null; /** */ double last_scale; /** */ double first_scale; /** */ int cnt = 0; /** */ double last_time; /** * * * @param p_cntrl * @param c_cntrl */ ProjectionControlListener(ProjectionControl p_cntrl, ContourControl c_cntrl) { this.p_cntrl = p_cntrl; this.c_cntrl = c_cntrl; double[] matrix = p_cntrl.getMatrix(); double[] rot_a = new double[3]; double[] trans_a = new double[3]; double[] scale_a = new double[1]; MouseBehaviorJ3D.unmake_matrix(rot_a, scale_a, trans_a, matrix); last_scale = scale_a[0]; first_scale = last_scale; LT_array = new LabelTransform[1000][][]; last_time = System.currentTimeMillis(); p_cntrl.addControlListener(this); c_cntrl.addProjectionControlListener(this, p_cntrl); } /** * * * @param e * * @throws RemoteException * @throws VisADException */ public synchronized void controlChanged(ControlEvent e) throws VisADException, RemoteException { double[] matrix = p_cntrl.getMatrix(); double[] rot_a = new double[3]; double[] trans_a = new double[3]; double[] scale_a = new double[1]; MouseBehaviorJ3D.unmake_matrix(rot_a, scale_a, trans_a, matrix); // - identify scale change events. if (!visad.util.Util.isApproximatelyEqual(scale_a[0], last_scale)) { double current_time = System.currentTimeMillis(); if (scale_a[0] / last_scale > 1.15 || scale_a[0] / last_scale < 1 / 1.15) { // BMF 2006-10-11 added loop for iterating controlChanged(...) calls to // avoid null pointer exceptions if (current_time - last_time < 3000) { if (LT_array != null) { for (int ii = 0; ii < cnt; ii++) { for (int kk = 0; kk < LT_array[ii][0].length; kk++) { for (int jj = 0; jj < LT_array[0].length; jj++) if (LT_array[ii][jj][kk] != null) LT_array[ii][jj][kk].controlChanged(first_scale, scale_a); } } } } else { if (LT_array != null) { for (int ii = 0; ii < cnt; ii++) { for (int kk = 0; kk < LT_array[ii][0].length; kk++) { for (int jj = 0; jj < LT_array[0].length; jj++) { if (LT_array[ii][jj][kk] != null) LT_array[ii][jj][kk].controlChanged(first_scale, scale_a); } } } } c_cntrl.reLabel(); } last_scale = scale_a[0]; } last_time = current_time; } } } /** * Class LabelTransform */ class LabelTransform { /** */ TransformGroup trans; /** */ Transform3D t3d; /** */ ProjectionControl proj; /** */ VisADGeometryArray label_array; /** */ VisADGeometryArray anchr_array; /** */ double[] matrix; /** */ double last_scale; /** */ double first_scale; /** */ float[] vertex; /** */ float[] anchr_vertex; /** */ double[] rot_a; /** */ double[] trans_a; /** */ double[] scale_a; /** */ int flag; /** */ float[] f_array; /** * * * @param trans * @param proj * @param label_array * @param f_array * @param flag */ LabelTransform(TransformGroup trans, ProjectionControl proj, VisADGeometryArray[] label_array, float[] f_array, int flag) { this.trans = trans; this.proj = proj; this.label_array = label_array[0]; this.anchr_array = label_array[1]; this.flag = flag; this.f_array = f_array; t3d = new Transform3D(); matrix = proj.getMatrix(); rot_a = new double[3]; trans_a = new double[3]; scale_a = new double[1]; MouseBehaviorJ3D.unmake_matrix(rot_a, scale_a, trans_a, matrix); last_scale = scale_a[0]; first_scale = last_scale; vertex = this.label_array.coordinates; anchr_vertex = this.anchr_array.coordinates; int vertexCount = this.label_array.vertexCount; } /** * * * @param first_scale * @param scale_a */ public void controlChanged(double first_scale, double[] scale_a) { trans.getTransform(t3d); double factor = 0; float f_scale = 0; if (flag == 0) { // -- label double k = first_scale; // - final scale factor = k / scale_a[0]; f_scale = (float) ((scale_a[0] - k) / scale_a[0]); } else { // -- expanding line segments double k = (f_array[0] / (f_array[1] - f_array[0])) * (f_array[1] / f_array[0] - first_scale / scale_a[0]) * scale_a[0]; factor = k / scale_a[0]; f_scale = (float) ((scale_a[0] - k) / scale_a[0]); } Vector3f trans_vec = new Vector3f(f_scale * anchr_vertex[0], f_scale * anchr_vertex[1], f_scale * anchr_vertex[2]); // These can't all be zero: non-affine transform if (!(factor == 0.0 && (trans_vec.x == 0.0 && trans_vec.y == 0.0 && trans_vec.z == 0.0))) { t3d.set((float) factor, trans_vec); trans.setTransform(t3d); } } }

Ads help maintain this website.