/*
* This code is part of Project Waterloo from King's College London
*
*
* Copyright King's College London 2011-
*
* @author Malcolm Lidierth, King's College London [Contact]
*
* Project Waterloo is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Project Waterloo 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
*/
package kcl.waterloo.graphics.plots2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import static kcl.waterloo.graphics.plots2D.BarExtra.MODE.GROUPED;
import static kcl.waterloo.graphics.plots2D.BarExtra.MODE.STACKED;
import static kcl.waterloo.graphics.plots2D.BarExtra.ORIENTATION.HORIZONTAL;
import static kcl.waterloo.graphics.plots2D.BarExtra.ORIENTATION.VERTICAL;
import kcl.waterloo.math.ArrayMath;
/**
* Abstract class that is extended by box-style concrete classes such as GJBar.
*
* Subclasses should implement the painting mechanism.
*
* @author ML
*/
public abstract class GJBox extends GJAbstractPlot {
public GJBox() {
super();
}
public GJBox(GJAbstractPlot p) {
super(p);
}
/**
* Returns an ArrayList of rectangles as Path2D instances.
*
* The position of each rectangle is set by the values in the XData property
* and the height by the YData values.
*
* @param x the x data
* @param y the y data
* @return an ArrayList, each element of which describes a rectangle
*/
public final ArrayList createBoxes(final double[] x, final double[] y) {
ArrayList array = new ArrayList();
double[] right = new double[x.length];
double[] upper = new double[x.length];
double[] left = new double[x.length];
double[] lower = new double[x.length];
BarExtra extra = (BarExtra) getDataModel().getExtraObject();
if (extra == null) {
return null;
}
double baseValue = extra.getBaseValue();
switch (extra.getOrientation()) {
case HORIZONTAL:
left = ArrayMath.min(y, baseValue);
right = ArrayMath.max(y, baseValue);
break;
case VERTICAL:
default:
lower = ArrayMath.min(y, baseValue);
upper = ArrayMath.max(y, baseValue);
}
final double[] dXl = new double[x.length];
final double[] dXr = new double[x.length];
switch (extra.getMode()) {
case HIST:
dXl[0] = 0.5d;
dXr[0] = (x[1] - x[0]) / 2d;
for (int k = 1; k < x.length - 1; k++) {
dXl[k] = (x[k] - x[k - 1]) / 2d;
dXr[k] = (x[k + 1] - x[k]) / 2d;
}
dXl[x.length - 1] = dXr[x.length - 2];
dXr[x.length - 1] = 0.5d;
break;
case HISTC:
dXl[0] = 0d;
dXr[0] = x[1] - x[0];
for (int k = 1; k < x.length - 1; k++) {
dXl[k] = 0d;
dXr[k] = x[k + 1] - x[k];
}
dXl[x.length - 1] = 0d;
dXr[x.length - 1] = 1d;
break;
case GROUPED:
case STACKED:
default:
ArrayMath.filli(dXl, extra.getBarWidth() / 2d);
ArrayMath.filli(dXr, extra.getBarWidth() / 2d);
}
int N = getMultiplexLength();
// Deal with stacking
if (N > 1 && ((BarExtra) getDataModel().getExtraObject()).getMode() == BarExtra.MODE.STACKED) {
double[] posLimit = new double[x.length / N + 1];
double[] negLimit = new double[x.length / N + 1];
ArrayMath.filli(posLimit, 0d);
ArrayMath.filli(negLimit, 0d);
for (int idx = 0; idx < x.length; idx++) {
int ref = (int) Math.floor((double) idx / (double) N);
switch (extra.getOrientation()) {
case HORIZONTAL:
if (y[idx] >= 0) {
left[idx] += posLimit[ref];
right[idx] += posLimit[ref];
} else {
left[idx] += negLimit[ref];
right[idx] += negLimit[ref];
}
break;
case VERTICAL:
if (y[idx] >= 0) {
lower[idx] += posLimit[ref];
upper[idx] += posLimit[ref];
} else {
lower[idx] += negLimit[ref];
upper[idx] += negLimit[ref];
}
}
if (y[idx] >= 0) {
posLimit[ref] += y[idx];
} else {
negLimit[ref] += y[idx];
}
}
}
switch (extra.getOrientation()) {
case HORIZONTAL:
left = getParentGraph().xPositionToPixeli(getParentGraph().getXTransform().getData(left));
right = getParentGraph().xPositionToPixeli(getParentGraph().getXTransform().getData(right));
if (N > 1 && ((BarExtra) getDataModel().getExtraObject()).getMode() == BarExtra.MODE.STACKED) {
// Align stacked bars
for (int k = 0; k < x.length; k++) {
int ref = (int) Math.floor((double) k / (double) N) * N;
lower[k] = getParentGraph().yPositionToPixel(getParentGraph().getYTransform().getData(x[ref] - dXl[k]));
upper[k] = getParentGraph().yPositionToPixel(getParentGraph().getYTransform().getData(x[ref] + dXr[k]));
}
} else {
lower = getParentGraph().yPositionToPixeli(getParentGraph().getYTransform().getData(ArrayMath.sub(x, dXl)));
upper = getParentGraph().yPositionToPixeli(getParentGraph().getYTransform().getData(ArrayMath.add(x, dXr)));
}
break;
case VERTICAL:
default:
lower = getParentGraph().yPositionToPixeli(getParentGraph().getYTransform().getData(lower));
upper = getParentGraph().yPositionToPixeli(getParentGraph().getYTransform().getData(upper));
if (N > 1 && ((BarExtra) getDataModel().getExtraObject()).getMode() == BarExtra.MODE.STACKED) {
// Align stacked bars
for (int k = 0; k < x.length; k++) {
int ref = (int) Math.floor((double) k / (double) N) * N;
left[k] = getParentGraph().xPositionToPixel(getParentGraph().getXTransform().getData(x[ref] - dXl[k]));
right[k] = getParentGraph().xPositionToPixel(getParentGraph().getXTransform().getData(x[ref] + dXr[k]));
}
} else {
left = getParentGraph().xPositionToPixeli(getParentGraph().getXTransform().getData(ArrayMath.sub(x, dXl)));
right = getParentGraph().xPositionToPixeli(getParentGraph().getXTransform().getData(ArrayMath.add(x, dXr)));
}
}
for (int i = 0; i < x.length; i++) {
if (((Double.isNaN(left[i])
|| Double.isNaN(right[i]))
|| Double.isNaN(upper[i]))
|| Double.isNaN(lower[i])) {
array.add(null);
} else {
array.add(new Rectangle2D.Double(left[i], upper[i],
right[i] - left[i], lower[i] - upper[i]));
}
}
return array;
}
@Override
public final Rectangle2D getDataRange() {
if (this.getXDataValues() != null && this.getYDataValues() != null) {
double[] x, y;
if (((BarExtra) getDataModel().getExtraObject()).getOrientation() == BarExtra.ORIENTATION.VERTICAL) {
x = ArrayMath.minmax(this.getXDataValues());
y = ArrayMath.minmax(this.getYDataValues());
} else {
y = ArrayMath.minmax(this.getXDataValues());
x = ArrayMath.minmax(this.getYDataValues());
}
Rectangle2D r = new Rectangle.Double(x[0], y[0], x[1] - x[0], y[1] - y[0]);
Rectangle2D r2;
for (GJPlotInterface p : getPlotList()) {
r2 = p.getDataRange();
r = r.createUnion(r2);
}
return r;
} else {
return new Rectangle.Double(0, 0, 0, 0);
}
}
}
Ads help maintain this website.