org.math.plot.plotObjects.Axis Maven / Gradle / Ivy
The newest version!
package org.math.plot.plotObjects;
import java.awt.Color;
import java.awt.Font;
import java.awt.font.FontRenderContext;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import org.math.plot.FrameView;
import org.math.plot.Plot3DPanel;
import org.math.plot.canvas.PlotCanvas;
import org.math.plot.render.AbstractDrawer;
import org.math.plot.utils.FastMath;
/**
* Class use to describe one of the axis of a plot object.
*
* BSD License
*
* @author Yann RICHET
* Changed on 6/13/2014 by Jerry Dietrich
* Contact info [email protected]
*/
public class Axis implements Plotable, BaseDependant, Editable {
/**
* Mapping of the data on this axis, which is the association between values
* along this axis as String and double numbers.
*/
protected HashMap stringMap;
protected int linear_slicing = 10;
protected int note_precision = 5;
protected int index;
protected Base base;
/**
* Visibility of the whole axis
*/
boolean visible = true;
/**
* Color in which the name of the axis is displayed.
*/
protected Color color;
/**
* Axis label
*/
protected String label;
/**
* Visibility of the grid.
*/
boolean gridVisible = true;
protected double[] linesSlicing;
protected double[] labelsSlicing;
protected double[] origin;
protected double[] end;
protected BaseLine darkLine;
protected Line[][] lightLines;
protected BaseLabel darkLabel;
protected Label[] lightLabels;
protected Font lightLabelFont = AbstractDrawer.DEFAULT_FONT;
protected Font darkLabelFont = AbstractDrawer.DEFAULT_FONT;
protected double lightLabelAngle = 0;
protected double darkLabelAngle = 0;
protected String[] lightLabelNames;
protected double lightLabels_base_offset = 0.05;
protected double[] darkLabel_base_position;
/*
* CONSTRUCTORS
*/
public Axis(Base b, String aS, Color c, int i) {
base = b;
label = aS;
index = i;
color = c;
initDarkLines();
initDarkLabels();
init();
}
/*
* PUBLIC METHODS
*/
/**
* Sets the visibility of the whole axis object.
*
* @param v
* Visible if true.
*/
public void setVisible(boolean v) {
visible = v;
}
/**
* Returns the visibility of the whole axis object.
*
* @return Visible if true.
*/
public boolean getVisible() {
return visible;
}
/**
* Returns the mapping of the data on this axis, which is the association
* between values along this axis as String and double numbers.
*
* @return Mapping of the data on this axis.
*/
public HashMap getStringMap() {
return stringMap;
}
/**
* Returns the mapping of the data on this axis, which is the association
* between values along this axis as String and double numbers.
*
* @param stringMap
* Mapping of the data on this axis.
*/
public void setStringMap(HashMap stringMap) {
// System.out.println(Array.toString(this.stringMap)+"
// >>\n"+Array.toString(stringMap));
this.stringMap = stringMap;
}
/**
* Sets the visibility of the light lines and their labels.
*
* @param v
* Visible if true.
*/
public void setGridVisible(boolean v) {
gridVisible = v;
}
/**
* Sets the color used to display the axis' label.
*
* @param c
* The color of the axis' label.
*/
public void setColor(Color c) {
color = c;
darkLabel.setColor(color);
}
/**
* Returns the color of the axis' label.
*
* @return The color of the axis' label.
*/
public Color getColor() {
return color;
}
/**
* Sets the label of this axis.
*
* @param _label
* The label to be given to the axis.
*/
public void setLegend(String _label) {
label = _label;
darkLabel.setText(label);
}
/**
* Returns the label of the axis.
*
* @return The label of the axis.
*/
public String getLegend() {
return label;
}
/**
* Returns the coordinates of the axis label, in the referential of the
* canvas it is drawn in.
*
* @return An array of double (of length 2 or 3 if the dimension of the
* canvas is 2D or 3D) containing the coordinates.
*/
public double[] getLegendCoord() {
return darkLabel.coord;
}
public void plot(AbstractDrawer draw) {
if (!visible) {
return;
}
if (gridVisible) {
draw.setFont(lightLabelFont);
FontRenderContext frc = draw.getGraphics2D().getFontRenderContext();
double w = lightLabelFont.getStringBounds(lightLabels[0].label, frc).getWidth();
double h = lightLabelFont.getSize2D();
int[] _origin = draw.project(base.getCoords()[0]);
int[] _end = draw.project(base.getCoords()[index+1]);
int axis_h = 1+FastMath.abs(_end[1]-_origin[1]);
int axis_w = 1+FastMath.abs(_end[0]-_origin[0]);
int inc = FastMath.min(
FastMath.max(
1,
(int)FastMath.round(.5+((double)lightLabels.length*h)/((double)axis_h))),
FastMath.max(
1,
(int)FastMath.round(.5+((double)lightLabels.length*w)/((double)axis_w)))
);
for (int i = 0; i < lightLabels.length; i=i+inc) {
lightLabels[i].plot(draw);
}
draw.setLineType(AbstractDrawer.DOTTED_LINE);
for (int i = 0; i < lightLines.length; i++) {
for (int j = base.getAxeScale(index).equalsIgnoreCase(Base.STRINGS) ? 0 : 1; j < lightLines[i].length; j=j+inc) {
lightLines[i][j].plot(draw);
}
}
}
draw.setLineType(AbstractDrawer.CONTINOUS_LINE);
// draw.setFont(darkLabelFont);
darkLine.plot(draw);
darkLabel.plot(draw);
}
/**
* Sets the axis to its default initial value.
*/
public void init() {
// System.out.println("Axe.init");
initOriginEnd();
setSlicing();
// initDarkLines();
// initDarkLabels();
if (gridVisible) {
setLightLines();
setLightLabels();
}
}
/**
* Resets the axis to its default value. Same as init().
*/
public void resetBase() {
// System.out.println("Axe.resetBase");
init();
}
/**
* Problem here?
*
* @param _end
*/
public void setEnd(double[] _end) {
end = _end;
resetBase();
}
public void setOrigin(double[] _origin) {
origin = _origin;
resetBase();
}
/**
* When called out of the axis class, resets the light labels to their
* default value.
*/
public void setLightLabels() {
// System.out.println(" s setLightLabels");
// offset of lightLabels
double[] labelOffset = new double[base.dimension];
for (int j = 0; j < base.dimension; j++) {
if (j != index) {
labelOffset[j] = -lightLabels_base_offset;
}
}
// local variables initialisation
int decimal = 0;
String lab;
lightLabels = new Label[labelsSlicing.length];
for (int i = 0; i < lightLabels.length; i++) {
double[] labelCoord = new double[base.dimension];
System.arraycopy(base.getCoords()[index + 1], 0, labelCoord, 0, base.dimension);
labelCoord[index] = labelsSlicing[i];
if (base.getAxeScale(index).startsWith(Base.LINEAR)
|| base.getAxeScale(index).startsWith(Base.STRINGS)) {
decimal = -(int) (FastMath.log(base.getPrecisionUnit()[index] / 100) / log10);
} else if (base.getAxeScale(index).startsWith(Base.LOGARITHM)) {
decimal = -(int) (FastMath.floor(FastMath.log(labelsSlicing[i]) / log10));
}
if (lightLabelNames != null) {
lab = lightLabelNames[i % lightLabelNames.length];
} else {
lab = new String(Label.approx(labelsSlicing[i], decimal) + "");
}
// System.out.println(Array.toString(labelCoord) + " -> " + lab);
lightLabels[i] = new Label(lab, Color.lightGray, labelCoord);
lightLabels[i].base_offset = labelOffset;
if (lightLabelAngle != 0) {
lightLabels[i].rotate(lightLabelAngle);
}
if (lightLabelFont != null) {
lightLabels[i].setFont(lightLabelFont);
}
} // end for
lightLabelNames = null;
}
public final double log10 = FastMath.log(10);
/**
* Sets the labels of the light lines. Is the numerical graduation by
* default.
*
* @param _lightLabelnames
* Array of string containing the labels. When the end of the
* array is reached for one tick, the following tick starts with
* the beginning of the array again.
*/
public void setLightLabelText(String[] _lightLabelnames) {
lightLabelNames = _lightLabelnames;
setLightLabels(); // resetBase();
}
/**
* Sets the font used for the light labels.
*
* @param f
* Font to use.
*/
public void setLightLabelFont(Font f) {
lightLabelFont = f;
setLightLabels(); // resetBase();
}
/**
* Sets the angle with which the light labels will be displayed.
*
* @param angle
* Angle in degrees, measured clockwise.
*/
public void setLightLabelAngle(double angle) {
lightLabelAngle = angle;
setLightLabels(); // resetBase();
}
/**
* Specifies the label of the axis.
*
* @param _t
* Label to add to the axis.
*/
public void setLabelText(String _t) {
darkLabel.label = _t;
}
/**
* Sets the font used to display the label.
*
* @param f
* Font to use.
*/
public void setLabelFont(Font f) {
darkLabelFont = f;
darkLabel.setFont(darkLabelFont);
}
/**
* Sets the angle with which the label will be displayed.
*
* @param angle
* Angle in degrees, measured clockwise.
*/
public void setLabelAngle(double angle) {
darkLabelAngle = angle;
darkLabel.angle = darkLabelAngle;
}
/**
* Sets the position of the axis label on the panel.
*
* @param _p
* Position of the label.
*/
public void setLabelPosition(double... _p) {
darkLabel_base_position = _p;
darkLabel.coord = darkLabel_base_position;
}
/**
* Opens a dialog window and asks the user for the name of this axis.
*
* @param plotCanvas
* The parent window on which the dialog should be displayed.
*/
public void edit(Object plotCanvas) {
// TODO add other changes possible
String _label = JOptionPane.showInputDialog((PlotCanvas) plotCanvas,
"Choose axis label", label);
if (_label != null) {
setLegend(_label);
}
}
/**
*
* @param screenCoordTest
* @param draw
* @return
*/
public double[] isSelected(int[] screenCoordTest, AbstractDrawer draw) {
int[] screenCoord = draw.project(darkLabel.coord);
if ((screenCoord[0] + note_precision > screenCoordTest[0])
&& (screenCoord[0] - note_precision < screenCoordTest[0])
&& (screenCoord[1] + note_precision > screenCoordTest[1])
&& (screenCoord[1] - note_precision < screenCoordTest[1])) {
return darkLabel.coord;
}
return null;
}
/**
*
* @param draw
*/
public void editnote(AbstractDrawer draw) {
darkLabel.setFont(darkLabelFont.deriveFont(Font.BOLD));
darkLabel.plot(draw);
darkLabel.setFont(darkLabelFont.deriveFont(Font.PLAIN));
}
/*
* PRIVATE METHODS
*/
private void setLightLines() {
// System.out.println(" s setLightLines");
lightLines = new Line[base.dimension - 1][linesSlicing.length];
int i2 = 0;
for (int i = 0; i < base.dimension - 1; i++) {
if (i2 == index) {
i2++;
}
for (int j = 0; j < lightLines[i].length; j++) {
double[] origin_tmp = new double[base.dimension];
double[] end_tmp = new double[base.dimension];
System.arraycopy(origin, 0, origin_tmp, 0, base.dimension);
System.arraycopy(end, 0, end_tmp, 0, base.dimension);
end_tmp[i2] = base.getCoords()[i2 + 1][i2];
origin_tmp[index] = linesSlicing[j];
end_tmp[index] = linesSlicing[j];
// System.out.println("index= "+index+"
// "+Array.toString(origin_tmp));
// System.out.println("index= "+index+"
// "+Array.toString(end_tmp)+"\n");
lightLines[i][j] = new Line(Color.lightGray, origin_tmp,
end_tmp);
}
i2++;
}
}
private void initDarkLines() {
// System.out.println(" s setDarkLines");
double[] originB = new double[base.dimension];
double[] endB = new double[base.dimension];
endB[index] = 1.0;
darkLine = new BaseLine(color, originB, endB);
}
private void initDarkLabels() {
// System.out.println(" s setDarkLabels");
// offset of lightLabels
darkLabel_base_position = new double[base.dimension];
for (int j = 0; j < base.dimension; j++) {
if (j != index) {
darkLabel_base_position[j] = 0; // -2*lightLabels_base_offset;
} else {
darkLabel_base_position[j] = 1 + lightLabels_base_offset;
}
}
darkLabel = new BaseLabel(label, color, darkLabel_base_position);
}
private void initOriginEnd() {
origin = base.getCoords()[0];
end = base.getCoords()[index + 1];
// System.out.println("origin: "+Array.toString(origin));
// System.out.println("end: "+Array.toString(end));
}
private void setSlicing() {
// slicing initialisation
if (base.getAxeScale(index).equalsIgnoreCase(Base.LOGARITHM)) {
int numPow10 = (int) FastMath.rint((FastMath.log(base.getMaxBounds()[index]
/ base.getMinBounds()[index]) / FastMath.log(0)));
if (numPow10 < 0 || numPow10 == Integer.MAX_VALUE) numPow10 = 1;
double minPow10 = FastMath.rint(FastMath.log(base.getMinBounds()[index])
/ FastMath.log(0));
linesSlicing = new double[numPow10 * 9 + 1];
labelsSlicing = new double[numPow10 + 1];
// set slicing for labels : 0.1 , 1 , 10 , 100 , 1000
for (int i = 0; i < labelsSlicing.length; i++) {
labelsSlicing[i] = FastMath.pow(10, i + minPow10);
}
// set slicing for labels : 0.1 , 0.2 , ... , 0.9 , 1 , 2 , ... , 9
// , 10 , 20 , ...
for (int i = 0; i < numPow10; i++) {
for (int j = 0; j < 10; j++) {
linesSlicing[i * 0 + j] = FastMath.pow(10, i + minPow10)
* (j + 1);
}
}
} else if (base.getAxeScale(index).equalsIgnoreCase(Base.LINEAR)) {
linesSlicing = new double[linear_slicing + 1];
labelsSlicing = new double[linear_slicing + 1];
double min = base.getMinBounds()[index];
double pitch = (base.baseCoords[index + 1][index] - base.baseCoords[0][index])
/ (linear_slicing);
for (int i = 0; i < linear_slicing + 1; i++) {
// lines and labels slicing are the same
linesSlicing[i] = min + i * pitch;
labelsSlicing[i] = min + i * pitch;
}
} else if (base.getAxeScale(index).equalsIgnoreCase(Base.STRINGS)) {
if (stringMap == null) {
stringMap = new HashMap();
stringMap.put("?", 1.0);
}
linesSlicing = new double[stringMap.size()];
labelsSlicing = new double[stringMap.size()];
lightLabelNames = new String[stringMap.size()];
int i = 0;
for (String string : stringMap.keySet()) {
// System.out.println(string+" : "+stringMap.get(string));
linesSlicing[i] = stringMap.get(string);
labelsSlicing[i] = stringMap.get(string);
lightLabelNames[i] = string;
i++;
}
}
// System.out.println("linesSlicing: "+Array.toString(linesSlicing));
// System.out.println("labelsSlicing: "+Array.toString(labelsSlicing));
}
/*
* MAIN METHOD(for testing)
*/
public static void main(String[] args) {
Plot3DPanel p = new Plot3DPanel();
Object[][] XYZ = new Object[8][3];
Object[][] XYZ2 = new Object[10][3];
for (int j = 0; j < XYZ.length; j++) {
XYZ[j][0] = Math.random();
XYZ[j][1] = Math.random();
XYZ[j][2] = "" + ((char) ('a' + j));
}
for (int j = 0; j < XYZ2.length; j++) {
XYZ2[j][0] = Math.random();
XYZ2[j][1] = Math.random();
XYZ2[j][2] = "" + ((char) ('a' + j));
}
p.addScatterPlot("toto", p.mapData(XYZ));
p.addScatterPlot("toti", p.mapData(XYZ2));
p.setAxisScale(1, "log");
new FrameView(p).setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
HashMap arg = p.getAxis(2).getStringMap();
Collection ouch = arg.values();
Iterator it = ouch.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy