/*
* 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.axes;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.text.DecimalFormat;
import org.opensourcephysics.display.DrawingPanel;
/**
* AbstractPolarAxis implements methods common to all polar axes.
*
* @author Wolfgang Christian
* @version 1.0
*/
public abstract class AbstractPolarAxis extends AbstractAxes implements PolarAxes {
static final double LOG10 = Math.log(10);
static int MAJOR_TIC = 5;
protected double dr = 1;
protected double dtheta = Math.PI/8;
protected boolean autospaceRings = true;
/**
* Creates polar axes that will display themselves within the given drawing panel.
*
* @param drawingPanel DrawingPanel
*/
protected AbstractPolarAxis(DrawingPanel drawingPanel) {
super(drawingPanel);
}
/**
* Automatically sets the spacing of the radial grid.
* @param autoscaleR
*/
public void autospaceRings(boolean autospace) {
this.autospaceRings = autospace;
}
/**
* Gets the spacing of the radial grid.
*/
public double getDeltaR() {
return dr;
}
/**
* Sets the spacing of the radial gridlines.
* @param dr
*/
public void setDeltaR(double dr) {
this.dr = dr;
}
/**
* Gets the spacing of the radial gridlines.
*/
public double getDeltaTheta() {
return dtheta;
}
/**
* Sets the spacing of the radial gridlines.
* @param dtheta in degree
*/
public void setDeltaTheta(double dtheta) {
this.dtheta = Math.abs(dtheta);
}
/**
* Method setLabelFormat
*
* @param formatString
*/
public void setLabelFormat(String formatString) {
labelFormat = new DecimalFormat(formatString);
}
/**
* Draws the spokes for the polar plot.
* @param panel
* @param g
*/
protected void drawRAxis(double dr, double rmax, DrawingPanel panel, Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g.setColor(gridcolor.darker());
int x1 = panel.xToPix(0);
int y1 = panel.yToPix(0);
int x2 = panel.xToPix(rmax);
g.drawLine(x1, y1, Math.min(x2, panel.getWidth()-panel.getRightGutter()), y1);
FontMetrics fm = g2.getFontMetrics();
int nLabels = (int) (panel.getXMax()/dr/MAJOR_TIC);
int stride = (nLabels>3) ? 2 : 1;
double rm = Math.min(rmax, panel.getXMax());
for(double r = (nLabels>3) ? stride*MAJOR_TIC*dr : MAJOR_TIC*dr; r<=rm; r += (stride*MAJOR_TIC*dr)) {
String label = getLabel(r);
int sW = fm.stringWidth(label)+4;
int sH = fm.getHeight();
g2.setColor(new Color(247, 247, 247));
int x0 = panel.xToPix(r), y0 = panel.yToPix(0);
g2.fill(new Rectangle2D.Double(x0-sW/2, y0+3, sW, sH));
g2.setColor(Color.black);
g2.draw(new Rectangle2D.Double(x0-sW/2, y0+3, sW, sH));
g2.setColor(drawingPanel.getForeground());
g2.drawString(label, x0-sW/2+2, y0+1+sH);
}
}
String getLabel(double r) {
if(r>=10) {
return Integer.toString((int) r);
}
return Double.toString(r);
}
/**
* Draws the rings for the polar plot.
* @param panel
* @param g
*
* @return double the ring separation used
*/
public double drawRings(double rmax, DrawingPanel panel, Graphics g) {
double dr = Math.max(this.dr, 1.0e-9);
if(autospaceRings) {
int exponent = (int) (Math.log(rmax)/LOG10);
double decade = Math.pow(10, exponent-1);
dr = decade;
while(rmax/dr>5*MAJOR_TIC) { // increase dr if we have more than 25 rings
dr *= 2;
if((dr/decade>3.5)&&(dr/decade<4.5)) {
dr = 5*decade;
decade *= 10;
}
}
} else {
int nrings = (int) (rmax/dr);
while(nrings>10*MAJOR_TIC) {
dr *= 2;
nrings = (int) (rmax/dr);
}
}
int xcenter = panel.xToPix(0);
int ycenter = panel.yToPix(0);
int xrad = (int) (panel.getXPixPerUnit()*rmax);
int yrad = (int) (panel.getYPixPerUnit()*rmax);
if(interiorColor!=null) {
g.setColor(interiorColor);
g.fillOval(xcenter-xrad, ycenter-yrad, 2*xrad, 2*yrad);
}
int counter = 0;
for(double r = 0; r<=rmax; r += dr) {
g.setColor(gridcolor);
xrad = panel.xToPix(r)-xcenter;
yrad = ycenter-panel.yToPix(r);
if(counter%MAJOR_TIC==0) {
g.setColor(gridcolor.darker());
}
g.drawOval(xcenter-xrad, ycenter-yrad, 2*xrad, 2*yrad);
counter++;
}
return dr;
}
/**
* Draws the spokes for the polar plot.
* @param panel
* @param g
*/
public void drawSpokes(double rmax, DrawingPanel panel, Graphics g) {
g.setColor(gridcolor);
for(double theta = 0; theta<Math.PI; theta += dtheta) {
int x1 = panel.xToPix(rmax*Math.cos(theta));
int y1 = panel.yToPix(rmax*Math.sin(theta));
int x2 = panel.xToPix(-rmax*Math.cos(theta));
int y2 = panel.yToPix(-rmax*Math.sin(theta));
g.drawLine(x1, y1, x2, y2);
}
}
}
/*
* 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
*/