/*
* Open Source Physics software is free software as described near the bottom of this code file.
*
* For additional information and documentation on Open Source Physics please see:
* <http://www.opensourcephysics.org/>
*/
package org.opensourcephysics.display;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
/**
* Grid draws a rectangular grid on a data panel.
*
* @author Wolfgang Christian
* @version 1.0
*/
public class Grid implements Drawable {
protected int nx, ny; // number of cells in x and y directions
protected double xmin, xmax, ymin, ymax;
protected double dx, dy;
protected Color color = new Color(200, 200, 200, 100);
protected GeneralPath generalPath = new GeneralPath();
protected boolean visible = true;
/**
* Constructs a square grid of the given size with a spacing of 1.
* @param n number of cells on a side
*/
public Grid(int n) {
this(n, n, 0, n, 0, n);
}
/**
* Constructs an (nx,ny) grid an x spacing of 1 and a y spacing of 1.
*
* @param nx the number of grid lines in the x direction
* @param ny the number of grid lines in the y direction
*/
public Grid(int nx, int ny) {
this(nx, ny, 0, nx, 0, ny);
}
/**
* Constructs a grid with the given number of x and y points and the given range.
*
* @param _nx the number of grid lines in the x direction
* @param _ny the number of grid lines in the y direction
* @param xmin
* @param xmax
* @param ymin
* @param ymax
*/
public Grid(int _nx, int _ny, double xmin, double xmax, double ymin, double ymax) {
nx = _nx;
ny = _ny;
setMinMax(xmin, xmax, ymin, ymax);
}
/**
* Sets the visible flag.
* Drawing will be disabled if visible is false.
*
* @param isVisible
*/
public void setVisible(boolean isVisible) {
visible = isVisible;
}
/**
* Checks if the grid is visible.
*
* @return true if visible; false otherwise
*/
public boolean isVisible() {
return visible;
}
/**
* Sets the drawing color.
*
* @param _color
*/
public void setColor(Color _color) {
color = _color;
}
/**
* Gets the drawing color.
*
* @return the color
*/
public Color getColor() {
return color;
}
/**
* Gets the x separation between x gid lines.
* @return dx
*/
public double getDx() {
return dx;
}
/**
* Gets the minimum value of x.
* @return xmin
*/
public double getXMin() {
return xmin;
}
/**
* Gets the maximum value of x.
* @return xamx
*/
public double getXMax() {
return xmax;
}
/**
* Gets the minimum value of y.
* @return ymin
*/
public double getYMin() {
return ymin;
}
/**
* Gets the maximum value of y.
* @return ymax
*/
public double getYMax() {
return ymax;
}
/**
* Gets the y separation between x gid lines.
* @return dy
*/
public double getDy() {
return dy;
}
/**
* Assigns a scale to the grid in world units.
*
* @param _xmin
* @param _xmax
* @param _ymin
* @param _ymax
*/
public void setMinMax(double _xmin, double _xmax, double _ymin, double _ymax) {
generalPath.reset();
xmin = (float) _xmin;
xmax = (float) _xmax;
ymin = (float) _ymin;
ymax = (float) _ymax;
if(nx>0) {
dx = (float) ((xmax-xmin)/nx);
} else {
dx = 1;
}
if(ny>0) {
dy = (float) ((ymax-ymin)/ny);
} else {
dy = 1;
}
if(!visible) { // don't calculate the general path unless this grid is visible
return;
}
float y = (float) ymin;
if(ny<=512) {
for(int i = 0; i<=ny; i++) {
generalPath.moveTo((float) xmin, y);
generalPath.lineTo((float) xmax, y);
y += dy;
}
}
float x = (float) xmin;
if(nx<=512) {
for(int i = 0; i<=nx; i++) {
generalPath.moveTo(x, (float) ymin);
generalPath.lineTo(x, (float) ymax);
x += dx;
}
}
}
public void draw(DrawingPanel panel, Graphics g) {
if(!visible) {
return;
}
if(Math.abs(panel.getXPixPerUnit()*(xmax-xmin)/nx)<4) {
return;
}
if(Math.abs(panel.getYPixPerUnit()*(ymax-ymin)/ny)<4) {
return;
}
Graphics2D g2 = (Graphics2D) g;
AffineTransform at = panel.getPixelTransform();
Shape s = generalPath.createTransformedShape(at);
g2.setColor(color);
g2.draw(s);
g2.setColor(Color.black);
}
/**
* Gets the cell column and row index for the specified location
*/
public int[] getCellPoint(double x, double y) {
int xindex = 0;
xindex = (int) Math.floor((x-xmin)/dx);
xindex = Math.max(0, xindex); // cannot be less than xmin
xindex = Math.min(nx, xindex); // cannot be greater than xmax
int yindex = 0;
yindex = (int) Math.floor((y-ymin)/dy);
yindex = Math.max(0, yindex); // cannot be less than ymin
yindex = Math.min(ny, yindex); // cannot be greater than ymax
return new int[] {xindex, xindex};
}
/**
* Gets the grid point closest to the specified location
*/
public Point2D.Double getClosestGridPoint(double x, double y) {
int index = 0;
index = (int) Math.round((x-xmin)/dx);
index = Math.max(0, index); // cannot be less than xmin
index = Math.min(nx, index); // cannot be greater than xmax
double gridx = xmin+dx*index;
index = (int) Math.round((y-ymin)/dy);
index = Math.max(0, index); // cannot be less than ymin
index = Math.min(ny, index); // cannot be greater than ymax
double gridy = ymin+dy*index;
return new Point2D.Double(gridx, gridy);
}
}
/*
* Open Source Physics software is free software; you can redistribute
* it and/or modify it under the terms of the GNU General Public License (GPL) as
* published by the Free Software Foundation; either version 2 of the License,
* or(at your option) any later version.
* Code that uses any portion of the code in the org.opensourcephysics package
* or any subpackage (subdirectory) of this package must must also be be released
* under the GNU GPL license.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA
* or view the license online at http://www.gnu.org/copyleft/gpl.html
*
* Copyright (c) 2007 The Open Source Physics project
* http://www.opensourcephysics.org
*/