/* * 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 */