package org.freehep.j3d.plot;
import javax.media.j3d.*;
import com.sun.j3d.utils.universe.SimpleUniverse;
import javax.swing.*;
import javax.vecmath.*;
/**
* A simple convenience class that end users can pop into their GUI to produce a
* lego plot.
*
* Warning: LegoPlot extends Canvas3D and thus is a heavyweight object.
* @author Joy Kyriakopulos (joyk@fnal.gov)
* @version $Id: LegoPlot.java 8584 2006-08-10 23:06:37Z duns $
*/
public class LegoPlot extends Plot3D
{
private Binned2DData data;
private LegoBuilder builder;
private Node plot;
private boolean logZscaling = false;
private boolean drawBlocks = true;
private boolean linesWhileAnim = true;
private int sparsifyThreshold = 600;
private AxisBuilder xAxis;
private AxisBuilder yAxis;
private ZAxisBuilder zAxis;
private String xAxisLabel = "X Axis";
private String yAxisLabel = "Y Axis";
private String zAxisLabel = "Z Axis";
private double xmin;
private double xmax;
private double ymin;
private double ymax;
private double zmin;
private double zmax;
public LegoPlot()
{
super();
}
public void setData(Binned2DData data)
{
this.data = data;
if (init) {
if (data.xMin() != xmin || data.xMax() != xmax) {
xmin = data.xMin();
xmax = data.xMax();
xAxis.createLabelsNTicks(xmin, xmax);
xAxis.apply();
}
if (data.yMin() != ymin || data.yMax() != ymax) {
ymin = data.yMin();
ymax = data.yMax();
yAxis.createLabelsNTicks(ymin, ymax);
yAxis.apply();
}
if (data.zMin() != zmin || data.zMax() != zmax) {
zmin = data.zMin();
zmax = data.zMax();
zAxis.createLabelsNTicks(zmin, zmax, logZscaling);
zAxis.apply();
}
if (logZscaling)
builder.updatePlot(new NormalizedBinned2DLogData(data));
else
builder.updatePlot(new NormalizedBinned2DData(data));
}
}
public boolean getLogZscaling()
{
return logZscaling;
}
public void setLogZscaling(boolean b)
{
// System.out.println("setting Log Scaling to: " + b + " from: " + logZscaling);
if (logZscaling != b) {
logZscaling = b;
if (data != null) {
zmin = data.zMin();
zmax = data.zMax();
zAxis.createLabelsNTicks(zmin, zmax, logZscaling);
zAxis.apply();
if (logZscaling)
builder.updatePlot(new NormalizedBinned2DLogData(data));
else
builder.updatePlot(new NormalizedBinned2DData(data));
}
}
}
public boolean getDrawBlocks()
{
return drawBlocks;
}
public void setDrawBlocks(boolean b)
{
if (drawBlocks != b) {
drawBlocks = b;
if (builder != null) {
builder.setDrawBlocks(b);
if (data != null) {
if (logZscaling)
builder.updatePlot(new NormalizedBinned2DLogData(data));
else
builder.updatePlot(new NormalizedBinned2DData(data));
}
}
}
}
public boolean getLinesWhileAnim()
{
return linesWhileAnim;
}
public void setLinesWhileAnim(boolean b)
{
if (linesWhileAnim != b) {
linesWhileAnim = b;
if (builder != null) {
builder.setLinesWhileAnim(b);
if (data != null) {
if (logZscaling)
builder.updatePlot(new NormalizedBinned2DLogData(data));
else
builder.updatePlot(new NormalizedBinned2DData(data));
}
}
}
}
public int getSparsifyThreshold()
{
return sparsifyThreshold;
}
public void setSparsifyThreshold(int s)
{
// The sparsify threshold is a limit on the number of bins that should be drawn when animating plot
// The lego builder's numWiredLines is the target number of bins that it will draw during animations
if (sparsifyThreshold != s) {
if (s > 1) {
sparsifyThreshold = s;
if (builder != null) {
builder.setNumWireLines(s); // Builder will sparsify when numWiredLines > # populated Bins
if (data != null) {
if (logZscaling)
builder.updatePlot(new NormalizedBinned2DLogData(data));
else
builder.updatePlot(new NormalizedBinned2DData(data));
}
}
}
else
System.out.println("LegoPlot: Invalid SparsifyThreshold: " + s);
}
}
public String getXAxisLabel()
{
return xAxisLabel;
}
public void setXAxisLabel(String s)
{
xAxisLabel = s;
xAxis.setLabel(s);
xAxis.apply();
}
public String getYAxisLabel()
{
return yAxisLabel;
}
public void setYAxisLabel(String s)
{
yAxisLabel = s;
yAxis.setLabel(s);
yAxis.apply();
}
public String getZAxisLabel()
{
return zAxisLabel;
}
public void setZAxisLabel(String s)
{
zAxisLabel = s;
zAxis.setLabel(s);
zAxis.apply();
}
protected Node createPlot()
{
builder = new LegoBuilder();
builder.setDrawBlocks(drawBlocks);
builder.setNumWireLines(sparsifyThreshold); // Builder will sparsify when numWiredLines/2 > # populated Bins
builder.setLinesWhileAnim(linesWhileAnim);
Node box = builder.buildOutsideBox();
if (logZscaling)
plot = builder.buildContent(new NormalizedBinned2DLogData(data));
else
plot = builder.buildContent(new NormalizedBinned2DData(data));
double[] tick = {0,.1,.2,.3,.4,.5,.6,.7,.8,.9,1.0};
String[] labels = {"0.0","0.2","0.4","0.6","0.8","1.0" };
xAxis = new XAxisBuilder(xAxisLabel,labels,tick);
yAxis = new YAxisBuilder(yAxisLabel,labels,tick);
zAxis = new ZAxisBuilder(zAxisLabel,labels,tick);
xAxis.createLabelsNTicks(data.xMin(), data.xMax());
yAxis.createLabelsNTicks(data.yMin(), data.yMax());
zAxis.createLabelsNTicks(data.zMin(), data.zMax(), logZscaling);
xAxis.apply();
yAxis.apply();
zAxis.apply();
Group g = new Group();
g.addChild(box);
g.addChild(plot);
g.addChild(xAxis.getNode());
g.addChild(yAxis.getNode());
g.addChild(zAxis.getNode());
return g;
}
// Add behavior to switch to "wire-frame" display when mouse is pressed
// by overriding defineMouseBehavior
protected BranchGroup defineMouseBehaviour(Node scene)
{
BranchGroup bg = super.defineMouseBehaviour(scene);
Bounds bounds = getDefaultBounds();
// change this to be switch node below i.e. not scene
if (plot instanceof Switch) {
Switch sw = (Switch)plot;
MouseDownUpBehavior mouseDnUp = new MouseDownUpBehavior(bounds, sw);
bg.addChild(mouseDnUp);
}
return bg;
}
}