/*
Copyright 2006 by Sean Luke and George Mason University
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package sim.portrayal3d.grid;
import sim.field.grid.*;
import sim.portrayal.*;
import sim.portrayal3d.*;
import sim.portrayal3d.simple.*;
import sim.util.*;
import sim.util.gui.*;
import javax.vecmath.*;
import javax.media.j3d.*;
import com.sun.j3d.utils.picking.*;
public class ValueGridPortrayal3D extends FieldPortrayal3D
{
String valueName;
public double scale;
public ColorMap map = new SimpleColorMap();
ValuePortrayal3D defaultPortrayal = new ValuePortrayal3D();
int width, height, length;
final MutableDouble valueToPass = new MutableDouble(0);
public ColorMap getMap() { return map;}
public void setMap(ColorMap m) { map = m; }
public String getValueName () { return valueName; }
public Portrayal getDefaultPortrayal()
{
return defaultPortrayal;
}
public void setField(Object field)
{
if (field instanceof IntGrid3D || field instanceof DoubleGrid3D) this.field = (AbstractGrid3D) field;
else if (field instanceof IntGrid2D || field instanceof DoubleGrid2D) this.field = (AbstractGrid2D) field;
else throw new RuntimeException("Invalid field for ValueGridPortrayal3D: " + field);
}
public Object getField() { return field; }
public ValueGridPortrayal3D()
{
this("Value", 1);
}
public ValueGridPortrayal3D(String valueName)
{
this(valueName, 1);
}
public ValueGridPortrayal3D(double s)
{
this("Value", s);
}
public ValueGridPortrayal3D(String valueName, double scale)
{
this.valueName = valueName;
this.scale = scale;
}
public PolygonAttributes polygonAttributes()
{
return ((Portrayal3D)(getPortrayalForObject(new ValuePortrayal3D.ValueWrapper(0,0,0,0,this)))).polygonAttributes();
}
public double newValue(int x, int y, int z)
{
if (field instanceof DoubleGrid3D)
return ((DoubleGrid3D)field).field[x][y][z];
else if (field instanceof IntGrid3D)
return ((IntGrid3D)field).field[x][y][z];
else if (field instanceof DoubleGrid2D)
return ((DoubleGrid2D)field).field[x][y];
else //if (field instanceof IntGrid2D)
return ((IntGrid2D)field).field[x][y];
}
public TransformGroup createModel()
{
TransformGroup globalTG = new TransformGroup();
globalTG.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
if (field == null) return globalTG;
Switch localSwitch = new Switch(Switch.CHILD_MASK);
localSwitch.setCapability(Switch.ALLOW_SWITCH_READ);
localSwitch.setCapability(Switch.ALLOW_SWITCH_WRITE);
localSwitch.setCapability(Group.ALLOW_CHILDREN_READ);
globalTG.addChild(localSwitch);
extractDimensions(); // set the width, height, and length based on the underlying grid
java.util.BitSet childMask = new java.util.BitSet(width*height*length);
Transform3D trans = new Transform3D();
Portrayal p = getPortrayalForObject(new ValuePortrayal3D.ValueWrapper(0,0,0,0,this));
if (!(p instanceof SimplePortrayal3D))
throw new RuntimeException("Unexpected Portrayal " + p + "for object " +
valueToPass + " -- expected a SimplePortrayal3D");
SimplePortrayal3D portrayal = (SimplePortrayal3D) p;
portrayal.setParentPortrayal(this);
int i = 0;
final int width = this.width;
final int height = this.height;
final int length = this.length;
for (int x=0;x<width;x++)
for (int y=0;y<height;y++)
for (int z=0;z<length;z++)
{
double value = newValue(x,y,z);
ValuePortrayal3D.ValueWrapper wrapper = new ValuePortrayal3D.ValueWrapper(value,x,y,z,this);
TransformGroup tg = portrayal.getModel(wrapper, null);
tg.setCapability(Group.ALLOW_CHILDREN_READ);
trans.setTranslation(new Vector3f(x,y,z));
trans.setScale(scale);
tg.setTransform(trans);
//tg.setUserData(wrapper); // already done when the object was created
localSwitch.addChild(tg);
if (map.getAlpha(value) > 2) // nontransparent
childMask.set(i);
else
childMask.clear(i);
i++;
}
localSwitch.setChildMask(childMask);
return globalTG;
}
public void updateModel(TransformGroup modelTG)
{
if (field == null) return;
extractDimensions();
Switch localSwitch = (Switch) modelTG.getChild(0);
java.util.BitSet childMask = localSwitch.getChildMask();
Portrayal p = getPortrayalForObject(valueToPass);
if (!(p instanceof SimplePortrayal3D))
throw new RuntimeException("Unexpected Portrayal " + p + "for object " +
valueToPass + " -- expected a SimplePortrayal3D");
SimplePortrayal3D portrayal = (SimplePortrayal3D) p;
portrayal.setParentPortrayal(this);
int i = 0;
final int width = this.width;
final int height = this.height;
final int length = this.length;
for (int x=0;x<width;x++)
for (int y=0;y<height;y++)
for (int z=0;z<length;z++)
{
TransformGroup tg = (TransformGroup)localSwitch.getChild(i);
// ValuePortrayal3D dispenses with its TransformGroup in order to achieve some
// additional speed. We recognize that fact here.
// TransformGroup g = (TransformGroup)(g.getChild(0));
// Shape3D shape = (Shape3D)(g.getChild(0));
Shape3D shape = (Shape3D)(tg.getChild(0));
ValuePortrayal3D.ValueWrapper wrapper = (ValuePortrayal3D.ValueWrapper)(shape.getUserData());
double value = newValue(x,y,z);
double oldValue = wrapper.lastVal;
if (value != oldValue) // change to new value
if (map.getAlpha(value) > 2) // nontransparent
{
childMask.set(i);
wrapper.lastVal = value;
portrayal.getModel(wrapper, tg);
}
else childMask.clear(i);
i++; // next index
}
localSwitch.setChildMask(childMask);
}
private void extractDimensions()
{
if (field instanceof IntGrid3D || field instanceof DoubleGrid3D)
{
AbstractGrid3D v = (AbstractGrid3D) field;
width = v.getWidth(); height = v.getHeight(); length = v.getLength();
}
else if (field instanceof IntGrid2D || field instanceof DoubleGrid2D)
{
AbstractGrid2D v = (AbstractGrid2D) field;
width = v.getWidth(); height = v.getHeight(); length = 1;
}
else throw new RuntimeException("Invalid field for ValueGridPortrayal3D: " + field);
}
public LocationWrapper completedWrapper(LocationWrapper w, PickIntersection pi, PickResult pr)
{
return w;
}
}