package ichthyop.util; import java.awt.*; import java.awt.Graphics2D; import java.awt.image.*; import java.util.*; import javax.swing.*; import ichthyop.*; import ichthyop.datanc.*; import java.awt.geom.Ellipse2D; public class SimulationUI extends JPanel { private static Population population; private static int hi, wi; private static double latmin; private static double latmax; private static double lonmin; private static double lonmax; private static BufferedImage background; private static RenderingHints hints = null; //---------------------------------------------------------------------------- public SimulationUI() { latmin = GetData.getLatMin(); latmax = GetData.getLatMax(); lonmin = GetData.getLonMin(); lonmax = GetData.getLonMax(); hi = -1; wi = -1; hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); hints.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); } //---------------------------------------------------------------------------- /** * * @param g Graphics */ public void paintComponent(Graphics g) { int h = getHeight(); int w = getWidth(); System.out.println(w + " " + h); Graphics2D g2 = (Graphics2D) g; g2.setRenderingHints(hints); /** Clear the graphics */ g2.clearRect(0, 0, w, h); /* Redraw the background when size changed */ if (hi != h || wi != w) { drawBackground(g2, w, h); hi = h; wi = w; } /* Draw the background into the graphics */ g2.drawImage(background, 0, 0, this); /* Draw the particles */ if (population != null) { ParticleUI particleUI = new ParticleUI(MainFrame.getValMin(), MainFrame.getValMax(), MainFrame.getDisplayColor()); Iterator iter = population.iterator(); Particle particle; while (iter.hasNext()) { particle = iter.next(); if (particle.isLiving()) { particleUI.draw(particle, w, h); g2.setColor(particleUI.getColor()); g2.fill(particleUI); } } } } //---------------------------------------------------------------------------- /** * Draws the background of the simulation. * @param g2 Graphics2D * @param w int * @param h int */ private void drawBackground(Graphics2D g2, int w, int h) { background = g2.getDeviceConfiguration().createCompatibleImage(w, h); Graphics2D graphic = background.createGraphics(); graphic.setColor(new Color(223, 212, 200)); graphic.fillRect(0, 0, w, h); CellUI cell = new CellUI(); for (int i = GetData.get_nx() - 1; i-- > 0; ) for (int j = GetData.get_ny() - 1; j-- > 0; ) { cell.draw(i, j, w, h); graphic.setColor(cell.getColor(i, j)); graphic.fillPolygon(cell); } } //-------------------------------------------------------------------------- /** * Transforms particle (x, y) coordinates into a screen point. * @param xgrid double * @param ygrid double * @param w int * @param h int * @return int[] */ public static int[] grid2Screen(double xgrid, double ygrid, int w, int h) { int[] point = new int[2]; int igrid, jgrid; double dx, dy; double[] p1, p2, p3, p4; igrid = (int) xgrid; jgrid = (int) ygrid; dx = xgrid - igrid; dy = ygrid - jgrid; p1 = grid2Screen(igrid, jgrid, w, h); p2 = grid2Screen(igrid + 1, jgrid, w, h); p3 = grid2Screen(igrid, jgrid + 1, w, h); p4 = grid2Screen(igrid + 1, jgrid + 1, w, h); for (int n = 0; n < 2; n++) { point[n] = (int) ( (1.d - dx) * (1.d - dy) * p1[n] + dx * (1.d - dy) * p2[n] + (1.d - dx) * dy * p3[n] + dx * dy * p4[n]); } return point; } //-------------------------------------------------------------------------- /** * Transforms a grid cell coordinate (i, j) into a screen point. * @param igrid int * @param jgrid int * @param w int * @param h int * @return double[] */ private static double[] grid2Screen(int igrid, int jgrid, int w, int h) { double[] point = new double[2]; point[0] = w * ( (GetData.getLon(igrid, jgrid) - lonmin) / Math.abs(lonmax - lonmin)); point[1] = h * (1.d - ( (GetData.getLat(igrid, jgrid) - latmin) / Math.abs(latmax - latmin))); return (point); } //---------------------------------------------------------------------------- public static void setPopulation(Population pop) { population = pop; } ////////////////////////////////////////////////////////////////////////////// private class CellUI extends Polygon { private int[][] points; private ArrayList listZones; final private Color bottom = new Color(0, 0, 150); final private Color surface = Color.CYAN; //-------------------------------------------------------------------------- public CellUI() { points = new int[4][2]; listZones = new ArrayList(0); if (MainFrame.isBG_SZone()) listZones.addAll(GetConfig.getReleaseZones()); if (MainFrame.isBG_RZone()) listZones.addAll(GetConfig. getRecruitmentZones()); } //-------------------------------------------------------------------------- public void draw(int i, int j, int w, int h) { this.reset(); points[0] = grid2Screen(i - 0.5f, j - 0.5f, w, h); points[1] = grid2Screen(i + 0.5f, j - 0.5f, w, h); points[2] = grid2Screen(i + 0.5f, j + 0.5f, w, h); points[3] = grid2Screen(i - 0.5f, j + 0.5f, w, h); for (int n = 0; n < 4; n++) { addPoint(points[n][0], points[n][1]); } } //-------------------------------------------------------------------------- private Color getColor(int i, int j) { if (GetData.isInWater(i, j)) { Color color = getColor(GetData.getBathy(i, j)); boolean found = false; Iterator iter = listZones.iterator(); Zone zone; while (!found && iter.hasNext()) { zone = iter.next(); if (zone.isXYInZone(i, j)) { color = zone.getColor(); found = true; } } return (color); } else { return Color.darkGray; } } //-------------------------------------------------------------------------- private Color getColor(double depth) { float xdepth = 0.f; if (depth < 0.1f) { return (Color.darkGray); } else { xdepth = (float) Math.abs( (GetData.getDepthMax() - depth) / GetData.getDepthMax()); } return (new Color( (int) (xdepth * surface.getRed() + (1 - xdepth) * bottom.getRed()), (int) (xdepth * surface.getGreen() + (1 - xdepth) * bottom.getGreen()), (int) (xdepth * surface.getBlue() + (1 - xdepth) * bottom.getBlue()))); } } ////////////////////////////////////////////////////////////////////////////// private class ParticleUI extends Ellipse2D.Double { private float valmin, valmax; private int displayColor; private Color color; final private Color colormin = Color.YELLOW; final private Color colormax = Color.RED; //-------------------------------------------------------------------------- public ParticleUI(float valmin, float valmax, int displayColor) { this.valmin = valmin; this.valmax = valmax; this.displayColor = displayColor; } //-------------------------------------------------------------------------- private void draw(Particle particle, int w, int h) { int[] corner = grid2Screen(particle.getX(), particle.getY(), w, h); //setFrame(corner[0] - 1, corner[1] - 1, 2, 2); setFrame(corner[0], corner[1], 1, 1); switch (displayColor) { case Resources.DISPLAY_DEPTH: color = getColor( (float) particle.getDepth()); break; case Resources.DISPLAY_TP: color = getColor( (float) particle.getTemperature()); break; case Resources.DISPLAY_ZONE: color = getColor(particle.getNumZoneInit()); break; default: color = Color.WHITE; } } //-------------------------------------------------------------------------- private Color getColor() { return color; } //-------------------------------------------------------------------------- private Color getColor(float value) { float xval = bound( (valmax - Math.abs(value)) / (valmax - valmin)); return (new Color( ( (int) (xval * colormin.getRed() + (1 - xval) * colormax.getRed())), ( (int) (xval * colormin.getGreen() + (1 - xval) * colormax.getGreen())), ( (int) (xval * colormin.getBlue() + (1 - xval) * colormax.getBlue())))); } //-------------------------------------------------------------------------- private Color getColor(int nZone) { return ( (Zone) GetConfig.getReleaseZones().get(nZone)).getColor(); } //-------------------------------------------------------------------------- private float bound(float x) { return Math.max(Math.min(1.f, x), 0.f); } } }