/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jlab.groot.graphics;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import org.jlab.groot.base.AxisAttributes;
import org.jlab.groot.base.ColorPalette;
import org.jlab.groot.base.FontProperties;
import org.jlab.groot.base.GStyle;
import org.jlab.groot.math.Dimension1D;
import org.jlab.groot.ui.LatexText;
/**
*
* @author gavalian
*/
public class GraphicsAxis {
private AxisAttributes attr = new AxisAttributes(AxisAttributes.X);
public static int AXISTYPE_COLOR = 1;
public static int AXISTYPE_HORIZONTAL = 2;
public static int AXISTYPE_VERTICAL = 3;
private int axisType = 2;
// private final Dimension1D axisRange = new Dimension1D();
private int numberOfMajorTicks = 10;
private Boolean isLogarithmic = false;
private Boolean isVertical = false;
private Boolean isColorAxis = false;
private final GraphicsAxisTicks axisTicks = new GraphicsAxisTicks();
/**
* default
* @param AXISTYPE
*/
public GraphicsAxis(int AXISTYPE){
this.axisType = AXISTYPE;
if(axisType==GraphicsAxis.AXISTYPE_COLOR){
isVertical = true;
isColorAxis = true;
}
if(axisType==GraphicsAxis.AXISTYPE_VERTICAL){
isVertical = true;
}
this.setDimension( 0, 100);
this.setRange( 0.0, 1.0);
initAttributes();
}
private void initAttributes() {
if(this.axisType == GraphicsAxis.AXISTYPE_HORIZONTAL){
try {
this.attr = GStyle.getAxisAttributesX().clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else if(this.axisType == GraphicsAxis.AXISTYPE_VERTICAL){
try {
this.attr = GStyle.getAxisAttributesY().clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if(this.axisType == GraphicsAxis.AXISTYPE_COLOR){
try {
this.attr = GStyle.getAxisAttributesZ().clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* sets the dimension for the axis for plotting.
* @param xmin
* @param xmax
* @return
*/
public final GraphicsAxis setDimension(int xmin, int xmax){
this.attr.getAxisDimension().setMinMax(xmin, xmax);
return this;
}
public void setAxisType(int type){
if(type == GraphicsAxis.AXISTYPE_COLOR){
this.isVertical = true;
this.isColorAxis = true;
}
}
public Dimension1D getDimension(){
return this.attr.getAxisDimension();
}
/**
* Sets the range of the axis, it also updates the axis labels.
* @param min
* @param max
* @return
*/
public final GraphicsAxis setRange(double min, double max){
//this.axisRange.setMinMax(min, max);
this.attr.setAxisAutoScale(false);
this.attr.setAxisMinimum(min);
this.attr.setAxisMaximum(max);
if(this.getAttributes().isLog()==true){
List ticks = this.attr.getRange().getDimensionTicksLog(this.numberOfMajorTicks);
//axisLabels.updateLog(ticks);
} else {
List ticks = this.attr.getRange().getDimensionTicks(this.numberOfMajorTicks);
this.axisTicks.init(ticks);
//axisLabels.update(ticks);
}
return this;
}
public void setTitle(String title){
attr.setAxisTitleString(title);
}
public boolean getLog(){
return this.getAttributes().isLog();
}
public void setLog(boolean flag){ this.getAttributes().setLog(flag);}
public Dimension1D getRange(){
return this.attr.getRange();
}
/**
* prints string representation of the axis.
*/
public void show(){
System.out.println(this.toString());
}
/**
* returns position along the axis, the dimension of the
* axis has to be set.
* @param value
* @return
*/
public double getAxisPosition(double value){
double fraction = this.attr.getRange().getFraction(value);
if( this.attr.getAxisDimension().getMin()< this.attr.getAxisDimension().getMax()){
//System.out.println("Getting axis position(fraction):"+this.axisType+" "+value+" "+this.attr.getAxisDimension().getPoint(fraction)+" "+fraction);
return this.attr.getAxisDimension().getPoint(fraction);
} else {
//System.out.println("Getting axis position(fraction):"+this.axisType+" "+value+" "+this.attr.getAxisDimension().getPoint(fraction)+" "+fraction+" "+Math.log10(fraction));
if(this.getLog()){
double axisMinimum = this.getDimension().getMin();
if(axisMinimum<1E-20){
axisMinimum = 1E-20;
}
if(fraction>1E-20){
return this.attr.getAxisDimension().getMin() -
fraction*Math.abs(this.attr.getAxisDimension().getMax()- this.attr.getAxisDimension().getMin());
}else{
return axisMinimum;
}
}else{
return this.attr.getAxisDimension().getMin() -
fraction*Math.abs(this.attr.getAxisDimension().getMax()- this.attr.getAxisDimension().getMin());
}
}
}
/**
* returns properties of the title font
* @return
*/
public FontProperties getTitleFont(){
return this.attr.getTitleFont();
}
/**
* returns properties for the label fonts.
* @return
*/
public FontProperties getLabelFont(){
return this.attr.getLabelFont();
}
public void setAxisFont(String fontname){
attr.setLabelFontName(fontname);
//axisLabelFont.setFontName(fontname);
axisTicks.updateFont(getLabelFont());
}
public void setAxisFontSize(int size){
attr.setLabelFontSize(size);
//axisLabelFont.setFontSize(size);
axisTicks.updateFont(getLabelFont());
}
public int getSize(Graphics2D g2d, boolean vertical){
if(vertical==true){
//return this.axisLabels.getAxisMaxWidth(g2d);
} else {
//return this.axisLabels.getAxisMaxHeight(g2d);
}
return 0;
}
public int getAxisDivisions(){
return this.numberOfMajorTicks;
}
public void setVertical(boolean flag){
this.isVertical = true;
}
public void setAxisDivisions(int ndiv){
this.numberOfMajorTicks = ndiv;
}
public List getAxisTicks(){
return null;//this.axisLabels.getTicks();
}
public int getAxisBounds(Graphics2D g2d){
double axisBounds = 0.0;
axisTicks.updateFont(getLabelFont());
List axisTexts = axisTicks.getAxisTexts();
double maxW = 0.0;
double maxH = 0.0;
for(LatexText text : axisTexts){
Rectangle2D bounds = text.getBoundsNumber(g2d);
//System.out.println(" bounds = " + (int) bounds.getHeight() );
if(bounds.getWidth()>maxW) maxW = bounds.getWidth();
if(bounds.getHeight()>maxH) maxH = bounds.getHeight();
}
if(this.isVertical==true){
axisBounds = maxW + this.attr.getLabelOffset();
} else {
axisBounds = maxH + this.attr.getLabelOffset();
}
if(this.attr.getTitle().getTextString().length()>1){
Rectangle2D rect = this.attr.getTitle().getBounds(g2d);
axisBounds += rect.getHeight() + this.attr.getTitleOffset();
}
//System.out.println( " Axis : " + axisTitle + " Max = " + isVertical +" " + (int) maxW + " " + (int) maxH + " " + (int) axisBounds);
return (int) axisBounds;
}
public void drawAxisGrid(Graphics2D g2d, int x, int y, int height){
if(this.isColorAxis==true) return;
g2d.setColor(new Color(200,200,200));
g2d.setStroke(GStyle.getStroke(2));
if(this.isVertical==false){
List ticks = axisTicks.getAxisTicks();
for(double tick : ticks){
//System.out.println(" tick = " + tick);
int xtick = (int) this.getAxisPosition(tick);
g2d.drawLine(xtick,y,xtick,y-height);
//g2d.drawLine(x,(int) tick,x+height,(int) tick);
}
} else {
List ticks = axisTicks.getAxisTicks();
for(double tick : ticks){
//System.out.println(" tick = " + tick);
int ytick = (int) this.getAxisPosition(tick);
g2d.drawLine(x,ytick,x+height,ytick);
//g2d.drawLine(x,(int) tick,x+height,(int) tick);
}
}
g2d.setColor(Color.black);
g2d.setStroke(new BasicStroke(1));
}
public void drawAxisMirror(Graphics2D g2d, int x, int y, int height){
if(this.isColorAxis==true) return;
g2d.setColor(Color.black);
g2d.setStroke(new BasicStroke(1));
//g2d.setStroke(GStyle.getStroke(2));
if(this.isVertical==false){
List ticks = axisTicks.getAxisTicks();
for(double tick : ticks){
//System.out.println(" tick = " + tick);
int xtick = (int) this.getAxisPosition(tick);
g2d.drawLine(xtick,y-height,xtick,y-height+this.getAttributes().getTickSize());
//g2d.drawLine(x,(int) tick,x+height,(int) tick);
}
} else {
List ticks = axisTicks.getAxisTicks();
for(double tick : ticks){
//System.out.println(" tick = " + tick);
int ytick = (int) this.getAxisPosition(tick);
g2d.drawLine(x+height-this.getAttributes().getTickSize(),ytick,x+height,ytick);
//g2d.drawLine(x,(int) tick,x+height,(int) tick);
}
}
}
public void drawAxis(Graphics2D g2d, int x, int y){
this.drawAxis(g2d, x, y, 0);
}
public void drawAxis(Graphics2D g2d, int x, int y, int height){
if(this.isColorAxis==true){
this.drawColorAxis(g2d, x, y);
return;
}
g2d.setColor(Color.BLACK);
//List ticks = axisRange.getDimensionTicks(this.numberOfMajorTicks);
//axisTicks.init(ticks);
this.setAxisDivisions(10);
axisTicks.updateFont(getLabelFont());
this.updateAxisDivisions(g2d);
if(height>5){
this.drawAxisMirror(g2d, x, y, height);
if(this.getAttributes().getGrid()==true){
this.drawAxisGrid(g2d, x, y, height);
}
}
List ticks = axisTicks.getAxisTicks();
List texts = axisTicks.getAxisTexts();
int labelOffset = attr.getLabelOffset();
int titleOffset = attr.getTitleOffset();
int tickLength = attr.getTickSize();
double midpoint = getAxisPosition(this.attr.getRange().getMin())*0.5 + 0.5*getAxisPosition(this.attr.getRange().getMax());
if(this.isVertical==false){
g2d.drawLine((int) this.attr.getAxisDimension().getMin(),y,(int) this.attr.getAxisDimension().getMax(),y);
for(int i = 0; i < ticks.size(); i++){
double tick = this.getAxisPosition(ticks.get(i));
g2d.drawLine((int) tick,y,(int) tick,y-tickLength);
texts.get(i).drawString(g2d, (int) tick, y + labelOffset, 1, 0);
}
int axisBounds = (int) texts.get(0).getBoundsNumber(g2d).getHeight();
attr.getTitle().drawString(g2d,
(int) midpoint,
y + axisBounds + labelOffset + titleOffset ,1,0);
} else {
g2d.drawLine(x,(int) this.attr.getAxisDimension().getMin(),x,(int) this.attr.getAxisDimension().getMax());
for(int i = 0; i < ticks.size(); i++){
double tick = this.getAxisPosition(ticks.get(i));
g2d.drawLine(x,(int) tick,x+tickLength,(int) tick);
texts.get(i).drawString(g2d, x-labelOffset, (int) tick, 2, 1);
}
int axisBounds = (int) texts.get(0).getBoundsNumber(g2d).getWidth();
for(int i=0; i ticks = axisTicks.getAxisTicks();
List texts = axisTicks.getAxisTexts();
g2d.setColor(Color.BLACK);
g2d.drawLine(x,(int) this.attr.getAxisDimension().getMin(),x,(int) this.attr.getAxisDimension().getMax());
int xstart = x + 4 + 8;
int ncolors = ColorPalette.getColorPallete3DSize();
double height = Math.abs( this.attr.getAxisDimension().getLength());
int tickSize = this.attr.getTickSize()/2;
//System.out.println(" Draw Z axis X = " + x + " Y = " + y);
for(int i = 0; i < ncolors; i++){
g2d.setColor(ColorPalette.getColorPalette3D(i));
int yp = (int) (( (double) i*height)/ncolors);
int offset = (int) (( (double) (i+1)*height)/ncolors);
int length = offset-yp;
//System.out.println("drawing color " + i + " yp = " + yp);
g2d.fillRect(x+4, (int) (y - offset), 8, length);
}
g2d.setColor(Color.BLACK);
g2d.drawRect(x + 4, (int) this.attr.getAxisDimension().getMax(),
8,(int) Math.abs( this.attr.getAxisDimension().getLength()));
for(int i = 0; i < ticks.size(); i++){
double tick = this.getAxisPosition(ticks.get(i));
g2d.drawLine(xstart,(int) tick,xstart+tickSize,(int) tick);
texts.get(i).drawString(g2d, xstart + tickSize + this.attr.getLabelOffset(), (int) tick, 0, 1);
}
}
private void updateAxisDivisions(Graphics2D g2d){
List ticks;
if(this.getLog()){
ticks = this.attr.getRange().getDimensionTicksLog(numberOfMajorTicks);
}else{
ticks = this.attr.getRange().getDimensionTicks(numberOfMajorTicks);
}
axisTicks.init(ticks);
axisTicks.updateFont(getLabelFont());
double heights = 0.0;
if(this.isVertical==true){
heights = axisTicks.getTextsHeight(g2d);
} else {
heights = axisTicks.getTextsWidth(g2d);
}
double axisLength = this.attr.getAxisDimension().getLength();
double fraction = heights/axisLength;
if(fraction>0.6){
int nticks = numberOfMajorTicks;
while(fraction>0.6&&nticks>2){
//System.out.println("Oh yeah - " + nticks + " fraction " + fraction );
nticks--;
if(this.getLog()){
ticks = this.attr.getRange().getDimensionTicksLog(nticks);
}else{
ticks = this.attr.getRange().getDimensionTicks(nticks);
}
axisTicks.init(ticks);
//heights = axisTicks.getTextsHeight(g2d);
if(this.isVertical==true){
heights = axisTicks.getTextsHeight(g2d);
} else {
heights = axisTicks.getTextsWidth(g2d);
}
fraction = heights/axisLength;
}
numberOfMajorTicks = nticks;
}
}
/*
public List getAxisStrings(){
return this.axisLabels.getLabels();
}*/
/**
* returns string representation of the axis.
* @return
*/
@Override
public String toString(){
StringBuilder str = new StringBuilder();
str.append("Axis : ");
str.append(" LOG = ");
str.append(this.isLogarithmic);
str.append(String.format(" (%4d x %4d ) : -> ", (int) this.attr.getAxisDimension().getMin(),
(int) this.attr.getAxisDimension().getMax()));
//str.append(axisLabels.toString());
return str.toString();
}
/**
* main program for testing the axis
* @param args
*/
public static void main(String[] args){
GraphicsAxis axis = new GraphicsAxis(GraphicsAxis.AXISTYPE_HORIZONTAL);
axis.setDimension(20, 100);
axis.setRange(0.0, 120.0);
//axis.setLog(true);
axis.show();
for(double d = 0; d < 120; d+=0.5){
System.out.println( d + " fraction = " + axis.getAxisPosition(d));
}
}
public static class GraphicsAxisTicks {
List axisTexts = new ArrayList();
List axisTicks = new ArrayList();
FontProperties axisFontProperty = new FontProperties();
void GraphicsAxisString(){
}
public List getAxisTicks(){
return this.axisTicks;
}
public List getAxisTexts(){
return this.axisTexts;
}
public void updateFont(FontProperties fp){
this.axisFontProperty.setFontName(fp.getFontName());
this.axisFontProperty.setFontSize(fp.getFontSize());
}
public double getTextsWidth(Graphics2D g2d){
double width = 0;
for(LatexText text : this.axisTexts){
Rectangle2D rect = text.getBoundsNumber(g2d);
width += rect.getWidth();
}
return width;
}
public double getTextsHeight(Graphics2D g2d){
double width = 0;
for(LatexText text : this.axisTexts){
Rectangle2D rect = text.getBoundsNumber(g2d);
width += rect.getHeight();
}
return width;
}
public void init(List ticks){
axisTexts.clear();
axisTicks.clear();
int significantFigures = this.getSignificantFigures(ticks);
if(significantFigures<0) significantFigures = -1;
for(int i = 0; i < ticks.size(); i++){
axisTicks.add(ticks.get(i));
}
for(int i = 0; i < axisTicks.size(); i++){
LatexText text = LatexText.createFromDouble(axisTicks.get(i),
significantFigures+1);
text.setFont(this.axisFontProperty.getFontName());
text.setFontSize(this.axisFontProperty.getFontSize());
axisTexts.add(text);
}
}
public int getSignificantFigures(List array){
if(array.size()<2) return 0;
double min = array.get(0);
double max = array.get(array.size()-1);
double difference = max-min;
int placeOfDifference = (int) Math.floor(Math.log(difference) / Math.log(10));
return -placeOfDifference;
}
}
public boolean isAutoScale() {
return attr.isAxisAutoScale();
}
public void setAutoScale(boolean b) {
attr.setAxisAutoScale(b);
}
public AxisAttributes getAttributes() {
return attr;
}
public void setAttributes(AxisAttributes attr) {
this.attr = attr;
}
public boolean getGrid() {
return attr.getGrid();
}
public void setGrid(boolean isGrid) {
attr.setGrid(isGrid);
}
public String getTitle() {
return attr.getAxisTitleString();
}
public int getTitleFontSize() {
return attr.getTitleFontSize();
}
public int getLabelFontSize() {
return attr.getLabelFontSize();
}
public double getMin() {
return attr.getAxisMinimum();
}
public double getMax() {
return attr.getAxisMaximum();
}
public void setShowAxis(boolean b) {
this.attr.setShowAxis(b);
}
public boolean isShowAxis(){
return this.attr.showAxis();
}
}
Ads help maintain this website.