package jeql.command.plot;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import jeql.awt.geom.DefaultPointConverter;
import jeql.awt.geom.Java2DConverter;
import jeql.awt.geom.PointConverter;
import jeql.util.ColorUtil;
import jeql.util.ImageUtil;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
public class Plot
{
private int width = 500;
private int height = 500;
private int borderSize = 0;
private int plotWidth = -1;
private int plotHeight = -1;
private Envelope worldExtent = null;
private String bgColor = "ffffff";
private String borderColor = "c0c0c0";
private List dataTables = new ArrayList();
private List labelTables = new ArrayList();
private BufferedImage plotImg = null;
private static final int IMG_TYPE = BufferedImage.TYPE_INT_ARGB;
public Plot() {
}
public void setBorderSize(int borderSize)
{
this.borderSize = borderSize;
}
public void setBorderColor(String color)
{
this.borderColor = color;
}
public void setWidth(int width)
{
this.width = width;
}
public int getWidth() { return width; }
public void setHeight(int height)
{
this.height = height;
}
public int getHeight() { return height; }
public void setBackground(String bgColor)
{
this.bgColor = bgColor;
}
public void setExtent(Envelope extent)
{
this.worldExtent = extent;
}
public Envelope getExtent() { return worldExtent; }
public void write(String filename)
throws IOException
{
RenderedImage fullImg = createBorderImage();
ImageIO.write(fullImg, ImageUtil.imageFormat(filename), new File(filename));
}
private int plotWidth()
{
return width - 2 * borderSize;
}
private int plotHeight()
{
return height - 2 * borderSize;
}
private RenderedImage createBorderImage()
{
if (borderSize == 0 && plotImg != null) return plotImg;
BufferedImage img = new BufferedImage(width, height, IMG_TYPE);
clear(img, borderColor);
if (plotImg != null) {
Raster plotRaster = plotImg.getData();
Raster transRaster = plotRaster.createTranslatedChild(borderSize, borderSize);
img.setData(transRaster);
}
return img;
}
private Graphics2D gr = null;
public Graphics2D getGraphics()
{
if (gr != null) return gr;
gr = plotImg.createGraphics();
// MD - no longer needed, done in ModelPointConverter
// apply standard transforms to invert Y axis
//gr.scale(1, -1);
//gr.translate(0, -plotHeight);
gr.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
return gr;
}
private Java2DConverter shapeConverter;
private PointConverter ptConverter;
public Java2DConverter getConverter() {
if (shapeConverter != null) return shapeConverter;
if (getExtent() != null) {
ptConverter = new ModelPointConverter(getExtent(), plotWidth(), plotHeight());
shapeConverter = new Java2DConverter(ptConverter);
}
else {
ptConverter = new DefaultPointConverter();
shapeConverter = new Java2DConverter();
}
return shapeConverter;
}
public Point2D convert(Coordinate modelPt)
{
return ptConverter.toView(modelPt);
}
public void init()
{
plotWidth = width - 2 * borderSize;
if (plotWidth < 0) plotWidth = 0;
plotHeight = height - 2 * borderSize;
if (plotHeight < 0) plotHeight = 0;
if (plotHeight > 0 && plotWidth > 0) {
// or TYPE_INT_RGB or TYPE_INT_ARGB_PRE ?
plotImg = new BufferedImage(plotWidth, plotHeight, IMG_TYPE);
clear(plotImg, bgColor);
}
}
private void clear(BufferedImage img, String color)
{
Graphics2D gr = img.createGraphics();
gr.setBackground(ColorUtil.RGBAtoColor(color));
gr.clearRect(0, 0, img.getWidth(), img.getHeight());
}
/**
* Transforms points from world coordinates to view coordinates.
*
* @author Martin Davis
*
*/
private static class ModelPointConverter
implements PointConverter
{
private double scale = 1.0;
private double worldMinX = 0.0;
private double worldMinY = 0.0;
private int viewHeight = 0;
public ModelPointConverter(Envelope worldExtent, int viewWidth, int viewHeight)
{
this.viewHeight = viewHeight;
double xScale = viewWidth / worldExtent.getWidth();
double yScale = viewHeight / worldExtent.getHeight();
scale = Math.min(xScale, yScale);
worldMinX = worldExtent.getMinX();
worldMinY = worldExtent.getMinY();
}
public Point2D toView(Coordinate modelCoordinate)
{
double vx = scale * (modelCoordinate.x - worldMinX);
double vy = viewHeight - scale * (modelCoordinate.y - worldMinY);
return new Point2D.Double(vx, vy);
}
}
}