/*
* Snapper.java
*
* Created on January 1, 2002, 1:40 PM
*/
package pharynx;
import java.io.*;
import java.text.*;
import java.util.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.media.jai.*;
import com.sun.media.jai.codec.*;
/**
* Snapper takes snapshots of the state of the simulation. These can be drawn
* in a widget or written to an image file.
*
* @author leon
* @version
*/
public class Snapper {
private Component c = null;
private Image basePic = null;
private BufferedImage filePic = null;
private static final int imageType = BufferedImage.TYPE_4BYTE_ABGR;
private static LumenDims ld = new LumenDims();
private static NumberFormat dnf; // time format in display
private static NumberFormat fnf; // time format in filename
{
dnf = NumberFormat.getInstance();
dnf.setMaximumFractionDigits(1);
fnf = NumberFormat.getInstance();
fnf.setMaximumFractionDigits(1);
fnf.setMinimumIntegerDigits(4);
fnf.setGroupingUsed(false);
}
public Snapper() {}
public Snapper(Component c) {
this();
this.c = c;
}
public void write(double t, PictureData pd, SimOptions options)
throws java.lang.NoClassDefFoundError {
int pw = ld.length() + 20;
int ph = (int) Math.ceil(ld.width()) + 20;
if (null == filePic)
filePic = new BufferedImage(pw, ph, imageType);
Graphics g = filePic.getGraphics();
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.black);
g2.fillRect(0, 0, pw, ph);
paint(g, pw, ph, pd, options);
String ts = fnf.format(t);
String fname = options.snapFile.getPath() +
ts + "." + options.snapExtension;
JAI.create("filestore", filePic, fname, options.snapType, null);
String txtname = options.snapFile.getPath() + ts + ".txt";
writetxt(txtname, t, pd, options);
}
private void writetxt(String txtname, double t, PictureData pd,
SimOptions options) {
PrintWriter fw;
try {
fw = new PrintWriter(new FileOutputStream(txtname));
}
catch(FileNotFoundException e) {
throw new CantCreateFileException("Can't create file " + txtname);
}
fw.println("time: " + t);
for(int i = 0; i < pd.things.size(); i++) {
PictureData.Thing ti = (PictureData.Thing) pd.things.get(i);
fw.println("particle at: " + (ld.length() - ti.x));
}
fw.close();
}
public void paint(
Graphics g,
int pw, int ph,
PictureData pd,
SimOptions options
) {
if (null == pd) return;
Graphics2D g2 = (Graphics2D) g;
Object aa = options.antialias ?
RenderingHints.VALUE_ANTIALIAS_ON :
RenderingHints.VALUE_ANTIALIAS_OFF;
initBasePic(pw, ph, pd, options);
g2.drawImage(basePic, 0, 0, null);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, aa);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_SPEED);
AffineTransform tx = g2.getTransform();
g2.translate((pw + pd.length)/2, ph/2);
Color openColor = Color.blue;
g2.setColor(openColor);
double x = 0.0;
for(int i = 0; i < pd.thickness.length; i++) {
double h = pd.currDiameter[i];
Shape r = new Rectangle2D.Double(x - pd.thickness[i],
-h/2,
pd.thickness[i],
h);
g2.fill(r);
x -= pd.thickness[i];
}
AffineTransform orig = g2.getTransform();
Collections.sort(pd.things, new Comparator() {
public int compare(Object o1, Object o2) {
PictureData.Thing t1 = (PictureData.Thing) o1;
PictureData.Thing t2 = (PictureData.Thing) o2;
return (t1.x - t1.bbx() < t2.x - t2.bbx()) ? -1 :
((t1.x -t1.bbx() == t2.x - t2.bbx()) ? 0 : 1);
}
public boolean equals(Object o1, Object o2) {
PictureData.Thing t1 = (PictureData.Thing) o1;
PictureData.Thing t2 = (PictureData.Thing) o2;
return (t1.x - t1.bbx() == t2.x - t2.bbx());
}
});
int j;
for(int i = 0; i < pd.things.size(); i = j) {
PictureData.Thing ti = (PictureData.Thing) pd.things.get(i);
double totalH = ti.bbh();
for(j = i + 1; j < pd.things.size(); j++) {
PictureData.Thing tj = (PictureData.Thing) pd.things.get(j);
if (tj.bbx() + tj.bbw() - tj.x <= ti.bbx() - ti.x) break;
totalH += tj.bbh();
}
double currentH = -totalH / 2;
for(int k = i; k < j; k++) {
PictureData.Thing tk = (PictureData.Thing) pd.things.get(k);
g2.translate(-tk.x, currentH - tk.bby());
g2.setColor(tk.color);
g2.fill(tk.shape());
g2.setTransform(orig);
currentH += tk.bbh();
}
}
g2.setTransform(tx);
g2.setColor(Color.white);
g2.setFont(g2.getFont().deriveFont(Font.BOLD));
g2.drawString(dnf.format(pd.t),
(pw - pd.length) / 2, (ph + pd.width) / 2);
}
private void initBasePic(int pw, int ph,
PictureData pd,
SimOptions options
) {
if (null != basePic) return;
if (null != c)
basePic = c.createImage(pw, ph);
else
basePic = new BufferedImage(pw, ph, imageType);
Graphics gb = basePic.getGraphics();
Graphics2D gb2 = (Graphics2D) gb;
Object aa = options.antialias ?
RenderingHints.VALUE_ANTIALIAS_ON :
RenderingHints.VALUE_ANTIALIAS_OFF;
gb2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, aa);
if (null != c) {
gb2.setColor(Color.black);
gb2.fillRect(0, 0, pw, ph);
}
gb2.setColor(new Color(0, 0, 0, 0)); //transparent black
gb2.fillRect(0, 0, pw, ph);
gb2.translate((pw + pd.length)/2, ph/2);
Color maxColor = Color.white;
double x = 0.0;
gb2.setColor(maxColor);
for(int i = 0; i < pd.thickness.length; i++) {
double h = pd.maxDiameter[i];
Shape r = new Rectangle2D.Double(x - pd.thickness[i],
-h/2,
pd.thickness[i],
h);
gb2.fill(r);
x -= pd.thickness[i];
}
}
}