package org.lemsml.jlems.viz.plot;
import java.util.ArrayList;
import org.lemsml.jlems.core.logging.E;
public final class WorldTransform {
private double wcx;
private double wcy;
private int pcx;
private int pcy;
private int canvasWidth;
private int canvasHeight;
private int dataAreaWidth;
private int dataAreaHeight;
private double dpdwx;
private double dpdwy;
private int leftMargin = 0;
private int rightMargin = 0;
private int topMargin = 0;
private int bottomMargin = 0;
private boolean xRescalable;
private boolean yRescalable;
private final static int IBIG = 20000;
private final static double SMALL = 1.e-7;
private final static double DBIG = 1.e9;
private boolean recordRange;
private double aspectRatio;
private boolean constantAspectRatio;
// following used for each paint to record limits;
private double vxmin;
private double vxmax;
private double vymin;
private double vymax;
// private boolean drawnInXRange;
// private boolean drawnInYRange;
// this is inelegant;
private boolean trialPanning = false;
private double wcxtp;
private double wcytp;
// for three D rotations
// private double wcz = 0.;
private double w2cx, w2cy, w2cz;
private double w3cx, w3cy, w3cz;
private double m3xx = 1., m3yy = 1., m3zz = 1.;
private double m3xy = 0., m3xz = 0., m3yx = 0., m3yz = 0., m3zx = 0., m3zy = 0.;
private double[][] m3B; // temp array container of above
// for continuous zoom
private double zoomCenX, zoomCenY, dpdwx0, dpdwy0, wcx0, wcy0;
private ArrayList<RangeListener> rangeListeners = new ArrayList<RangeListener>();
private RotationListener rotationListener;
private final Size p_pixelSize;
public WorldTransform() {
setWidth(100);
setHeight(100);
setXRescalable(true);
setYRescalable(true);
setAspectRatioFree();
dpdwx = 1.;
dpdwy = 1.;
wcx = 0.;
wcy = 0.;
p_pixelSize = new Size(0., 0.);
}
public void setCanvasSize(int w, int h) {
setWidth(w);
setHeight(h);
System.out.println("SCS " + w + " " + h);
}
public int getWidth() {
return canvasWidth;
}
public int getHeight() {
return canvasHeight;
}
public int getLeftMargin() {
return leftMargin;
}
public int getBottomMargin() {
return bottomMargin;
}
public void setMargins(int l, int r, int b, int t) {
leftMargin = l;
rightMargin = r;
topMargin = t;
bottomMargin = b;
}
public boolean isOnCanvas(double x, double y) {
return intIsOnCanvas(powx(x), powy(y));
}
public boolean intIsOnCanvas(int x, int y) {
return (x > -10 && x < canvasWidth + 10 && y > -10 && y < canvasHeight + 10);
}
public void addRangeListener(RangeListener rl) {
rangeListeners.add(rl);
rl.rangeChanged(getXYXYLimits());
}
public void setRotationListener(RotationListener rl) {
rotationListener = rl;
}
public void fixRanges() {
notifyRangeChange();
}
public void rangeChange() {
notifyRangeChange();
}
public void notifyRangeChange() {
double[] lims = getXYXYLimits();
for (RangeListener rl : rangeListeners) {
rl.rangeChanged(lims);
}
// System.out.println("notified rc " + lims[0] + " " + lims[2]);
}
public void setPixelScalingFromTop(double d) {
pSetXRange(0., d * getCanvasWidth());
pSetYRange(-1. * d * getCanvasHeight(), 0.);
notifyRangeChange();
}
public void setAspectRatioFree() {
constantAspectRatio = false;
}
public void setFixedAspectRatio(double f) {
setAspectRatio(f);
}
public void setAspectRatio(double f) {
aspectRatio = f;
constantAspectRatio = true;
}
public void setXRescalable(boolean b) {
xRescalable = b;
}
public void setYRescalable(boolean b) {
yRescalable = b;
}
void clearRanges() {
vxmin = DBIG;
vymin = DBIG;
vxmax = -1 * DBIG;
vymax = -1 * DBIG;
// drawnInXRange = false;
// drawnInYRange = false;
}
void startRangeRecording() {
clearRanges();
recordRange = true;
}
void stopRangeRecording() {
recordRange = false;
}
public void setWidth(int w) {
if (canvasWidth != w) {
canvasWidth = w;
dataAreaWidth = (canvasWidth - leftMargin - rightMargin) / 2;
if (dataAreaWidth < 2) {
dataAreaWidth = 2;
}
pcx = leftMargin + dataAreaWidth;
notifyRangeChange();
}
}
public void setHeight(int h) {
if (canvasHeight != h) {
canvasHeight = h;
dataAreaHeight = (canvasHeight - topMargin - bottomMargin) / 2;
if (dataAreaHeight < 2) {
dataAreaHeight = 2;
}
pcy = bottomMargin + dataAreaHeight;
notifyRangeChange();
}
}
public int getCanvasWidth() {
return canvasWidth;
}
public int getCanvasHeight() {
return canvasHeight;
}
public double getWorldCanvasWidth() {
return canvasWidth / dpdwx;
}
public boolean isShowing(double x, double y) {
int ix = powx(x);
int iy = powy(y);
return (ix > 5 && iy > 5 && ix < canvasWidth - 50 && iy < canvasHeight - 5); // ADHOC
}
int[] intDeviceX(double[] wx) {
int n = wx.length;
int[] idev = new int[n];
if (recordRange) {
for (int i = 0; i < n; i++) {
idev[i] = qpowx(wx[i]);
}
} else {
for (int i = 0; i < n; i++) {
idev[i] = powx(wx[i]);
}
}
return idev;
}
int[] intDeviceY(double[] wy) {
int n = wy.length;
int[] idev = new int[n];
if (recordRange) {
for (int i = 0; i < n; i++) {
idev[i] = qpowy(wy[i]);
}
} else {
for (int i = 0; i < n; i++) {
idev[i] = powy(wy[i]);
}
}
return idev;
}
float[] floatDeviceX(double[] wx) {
int n = wx.length;
float[] fdev = new float[n];
if (recordRange) {
for (int i = 0; i < n; i++) {
fdev[i] = qpowx(wx[i]);
}
} else {
for (int i = 0; i < n; i++) {
fdev[i] = powx(wx[i]);
}
}
return fdev;
}
float[] floatDeviceY(double[] wy) {
int n = wy.length;
float[] fdev = new float[n];
if (recordRange) {
for (int i = 0; i < n; i++) {
fdev[i] = qpowy(wy[i]);
}
} else {
for (int i = 0; i < n; i++) {
fdev[i] = powy(wy[i]);
}
}
return fdev;
}
public Size getPixelSize() {
p_pixelSize.set(1. / dpdwx, 1. / dpdwy);
return p_pixelSize;
}
public double getPixelArea() {
return 1./ dpdwx * 1. / dpdwy;
}
protected double wopx(int x) {
return wcx + (x - pcx) / dpdwx;
}
protected double wopy(int y) {
return wcy + (canvasHeight - y - pcy) / dpdwy;
}
protected int xpix(double xr) {
return (int)(Math.round(dpdwx * xr));
}
protected int ypix(double yr) {
return (int)(Math.round(dpdwy * yr));
}
protected int powx(double xr) {
double f = dpdwx * (xr - wcx);
if (f > IBIG) {
f = IBIG;
}
if (f < -IBIG) {
f = -IBIG;
}
int ii = (pcx + (int)f);
if (recordRange) {
if (xr > vxmax) {
vxmax = xr;
}
if (xr < vxmin) {
vxmin = xr;
}
}
if (ii > 0 && ii < canvasWidth) {
// drawnInXRange = true;
}
return ii;
}
protected int powy(double yr) {
double f = dpdwy * (yr - wcy);
if (f > IBIG) {
f = IBIG;
}
if (f < -IBIG) {
f = -IBIG;
}
int ii = (canvasHeight - (pcy + (int)f));
if (recordRange) {
if (yr > vymax) {
vymax = yr;
}
if (yr < vymin) {
vymin = yr;
}
}
if (ii > 0 && ii < canvasHeight) {
// drawnInYRange = true;
}
return ii;
}
protected float fpowx(double xr) {
float f = (float)(dpdwx * (xr - wcx));
return pcx + f;
}
protected float fpowy(double yr) {
float f = (float)(dpdwy * (yr - wcy));
float ret = (canvasHeight - (pcy + f));
return ret;
}
private int qpowx(double xr) {
return (int)(pcx + dpdwx * (xr - wcx));
}
private int qpowy(double yr) {
return (int)(canvasHeight - (pcy + dpdwy * (yr - wcy)));
}
public int pubPowx(double xr) {
return powx(xr);
}
public int pubPowy(double yr) {
return powy(yr);
}
public Position getWorldPosition(int x, int y) {
return new Position(wopx(x), wopy(y));
}
public double pubWopx(int x) {
return wopx(x);
}
public double pubWopy(int y) {
return wopy(y);
}
public int pubPixDx(double dxr) {
return (int)(dpdwx * dxr);
}
public int pubPixDy(double dyr) {
return (int)(dpdwy * dyr);
}
public double dPdX() {
return dpdwx;
}
public double dPdY() {
return dpdwy;
}
public double pubDyDpix() {
return 1. / dpdwy;
}
public double pubDxDpix() {
return 1. / dpdwx;
}
public double wxLeft() {
return wcx - dataAreaWidth / dpdwx;
}
public double wxRight() {
return wcx + dataAreaWidth / dpdwx;
}
public double wyBottom() {
return wcy - dataAreaHeight / dpdwy;
}
public double wyTop() {
return wcy + dataAreaHeight / dpdwy;
}
private void enforceAspectRatioY() {
if (xRescalable) {
dpdwx = 1. / aspectRatio * dpdwy;
} else if (yRescalable) {
dpdwy = aspectRatio * dpdwx;
}
}
private void enforceAspectRatioX() {
if (yRescalable) {
dpdwy = aspectRatio * dpdwx;
} else if (xRescalable) {
dpdwx = 1. / aspectRatio * dpdwy;
}
}
/*
* public void shiftRanges (double twcx, double twcy) { // set wcx, wcy such
* that the point that is at xdown, ydown in the; // twcx, twcy coordis is
* now at x, y;
*
* double dx, dy; if (xRescalable) { dx = (ms.px - ms.px0) / dpdwx; wcx =
* twcx - dx; } if (yRescalable) { dy = (ms.py - ms.py0) / dpdwy; wcy = twcy +
* dy; } if (constantAspectRatio) enforceAspectRatioY(); recordLimits(); }
*/
private void zoomAbout(double f, int xc, int yc) {
zoomAbout(f, f, xc, yc);
}
private void zoomAbout(double fx, double fy, int xc, int yc) {
xZoomAbout(fx, xc);
yZoomAbout(fy, yc);
if (constantAspectRatio) {
enforceAspectRatioY();
}
rangeChange();
}
private void xZoomAbout(double f, int xc) {
// NB, here, as everywhere, integer coordinates are measured from;
// the TOP left corner, so small y is at the top of the window;
double xWorld = wopx(xc);
if (xc > leftMargin && xRescalable) {
wcx = xWorld + f * (wcx - xWorld);
dpdwx /= f;
if (dpdwx > 1. / SMALL) {
dpdwx = 1. / SMALL;
}
}
}
private void yZoomAbout(double f, int yc) {
double yWorld = wopy(yc);
if (yc < canvasHeight - bottomMargin && yRescalable) {
wcy = yWorld + f * (wcy - yWorld);
dpdwy /= f;
if (dpdwy > 1. / SMALL) {
dpdwy = 1. / SMALL;
}
}
}
void initializeZoom(int xc, int yc) {
zoomCenX = wopx(xc);
zoomCenY = wopy(yc);
dpdwx0 = dpdwx;
dpdwy0 = dpdwy;
wcx0 = wcx;
wcy0 = wcy;
}
void dragZoom(double fxin, double fyin, int xc, int yc) {
double fx = fxin;
double fy = fyin;
if (constantAspectRatio) {
fx = fy;
}
if (xc > leftMargin && xRescalable) {
wcx = zoomCenX + fx * (wcx0 - zoomCenX);
dpdwx = dpdwx0 / fx;
if (dpdwx > 1. / SMALL) {
dpdwx = 1. / SMALL;
}
}
if (yc < canvasHeight - bottomMargin && yRescalable) {
wcy = zoomCenY + fy * (wcy0 - zoomCenY);
dpdwy = dpdwy0 / fy;
if (dpdwy > 1. / SMALL) {
dpdwy = 1. / SMALL;
}
}
if (constantAspectRatio) {
enforceAspectRatioY();
}
notifyRangeChange();
}
/*
*
*
* if (y > topMargin && x < width - rightMargin) {
*
*
* } if (y < topMargin) { tickGridx = tickGridx + (f < 1. ? -1 : 1); } if (x >
* width - rightMargin) { tickGridy = tickGridy + (f < 1. ? -1 : 1); }
*
* enforceRangeConstraints(); recordLimits(); }
*
*
*
*/
public void reframe(Box b) {
setXRange(b.getXmin(), b.getXmax());
setYRange(b.getYmin(), b.getYmax());
//System.out.println("wt set ranges " + b.getXmin() + " " + b.getXmax());
notifyRangeChange();
}
public void setXRange(double xl, double xh) {
pSetXRange(xl, xh);
notifyRangeChange();
}
public void setYRange(double yl, double yh) {
pSetYRange(yl, yh);
notifyRangeChange();
}
private void pSetXRange(double xlin, double xhin) {
double xl = xlin;
double xh = xhin;
if (xh < xl) {
double xt = xh;
xh = xl;
xl = xt;
}
if (xRescalable) {
if (xh <= xl) {
xh += 0.5;
xl -= 0.5;
}
wcx = 0.5 * (xl + xh);
if (xh <= xl + SMALL) {
xh = xl + SMALL;
}
dpdwx = 2. * dataAreaWidth / (xh - xl);
}
if (constantAspectRatio) {
enforceAspectRatioX();
}
}
public void ensureCovers(double xl, double yl, double xh, double yh) {
// set tighter constraint last; other first to get center
if ((xh - xl) * dataAreaHeight > (yh - yl) * dataAreaWidth) {
pSetYRange(yl, yh);
pSetXRange(xl, xh);
} else {
pSetXRange(xl, xh);
pSetYRange(yl, yh);
}
notifyRangeChange();
}
private void pSetYRange(double ylin, double yhin) {
double yl = ylin;
double yh = yhin;
if (yh < yl) {
double yt = yh;
yh = yl;
yl = yt;
}
if (yRescalable) {
if (yh <= yl) {
yl -= 0.5;
yh += 0.5;
}
wcy = 0.5 * (yl + yh);
if (yh <= yl + SMALL) {
yh = yl + SMALL;
}
dpdwy = 2. * dataAreaHeight / (yh - yl);
}
if (constantAspectRatio) {
enforceAspectRatioY();
}
rangeChange();
}
public double[] getXYXYLimits() {
double[] range = new double[4];
range[0] = wxLeft();
range[1] = wyBottom();
range[2] = wxRight();
range[3] = wyTop();
return range;
}
public double[] getXRange() {
double[] d = { wxLeft(), wxRight() };
return d;
}
public double[] getYRange() {
double[] d = { wyBottom(), wyTop() };
return d;
}
public void setXYXYLimits(double xl, double yl, double xh, double yh) {
if (constantAspectRatio) {
// assume aspect ratio is 1 for now!!! ---------- TODO;
if ((xh - xl) / (canvasWidth - leftMargin - rightMargin) > (yh - yl)
/ (canvasHeight - topMargin - bottomMargin)) {
pSetYRange(yl, yh);
pSetXRange(xl, xh);
} else {
pSetXRange(xl, xh);
pSetYRange(yl, yh);
}
} else {
pSetXRange(xl, xh);
pSetYRange(yl, yh);
}
notifyRangeChange();
}
void applyRecordedRange() {
double dx = 0.1 * (vxmax - vxmin);
double dy = 0.1 * (vymax - vymin);
double xa = vxmin - dx;
double xb = vxmax + dx;
double ya = vymin - dy;
double yb = vymax + dy;
if (vxmin > 1.e8 && vxmax < -1.e8) {
setXYXYLimits(0., 0., 1., 1.);
} else {
setXYXYLimits(xa, ya, xb, yb);
}
}
// default mouse coanvas ignores these - subclasses should
// do something more useful
public void boxSelected(int x0, int y0, int x1, int y1) {
pSetXRange(wopx(x0), wopx(x1));
pSetYRange(wopy(y0), wopy(y1));
notifyRangeChange();
}
void zoom(double fac, int xc, int yc) {
zoomAbout(fac, xc, yc);
}
void zoom(double xfac, double yfac, int xc, int yc) {
zoomAbout(xfac, yfac, xc, yc);
}
void trialPan(int xfrom, int yfrom, int xto, int yto) {
if (!trialPanning) {
wcxtp = wcx;
wcytp = wcy;
trialPanning = true;
}
// not final - should be smarter here - just shift an image EFF;
wcx = wcxtp - (wopx(xto) - wopx(xfrom));
wcy = wcytp - (wopy(yto) - wopy(yfrom));
rangeChange();
}
void permanentPan(int xfrom, int yfrom, int xto, int yto) {
if (!trialPanning) {
wcxtp = wcx;
wcytp = wcy;
}
wcx = wcxtp - (wopx(xto) - wopx(xfrom));
wcy = wcytp - (wopy(yto) - wopy(yfrom));
trialPanning = false;
rangeChange();
}
public int[] getIntPosition(double x, double y) {
int[] ixy = {powx(x), powy(y)};
return ixy;
}
// 3D transforms and mouse manipulation
protected double xProj (double x, double y, double z) {
return w2cx + m3xx * (x - w3cx) + m3xy * (y - w3cy) + m3xz * (z - w3cz);
}
protected double yProj (double x, double y, double z) {
return w2cy + m3yx * (x - w3cx) + m3yy * (y - w3cy) + m3yz * (z - w3cz);
}
protected double zProj (double x, double y, double z) {
return w2cz + m3zx * (x - w3cx) + m3zy * (y - w3cy) + m3zz * (z - w3cz);
}
public double[] project(double x, double y, double z) {
double[] v = {xProj(x,y,z), yProj(x,y,z), zProj(x,y,z)};
return v;
}
public double[] deProject (double x, double y, double z) {
// deproject the point x, y, w3cz into 3D x,y,z
double xu = x - w2cx;
double yu = y - w2cy;
double zu = z - w2cz;
double[] v = new double[3];
double det = (m3xx * (m3yy * m3zz - m3zy * m3yz) -
m3xy * (m3yx * m3zz - m3zx * m3yz) +
m3xz * (m3yx * m3zy - m3zx * m3yy));
v[0] = w3cx + ((m3xy * (m3yz * zu - m3zz * yu ) -
m3xz * (m3yy * zu - m3zy * yu ) +
xu * (m3yy * m3zz - m3zy * m3yz) )) / det;
v[1] = w3cy + (-(m3xx * (m3yz * zu - m3zz * yu ) -
m3xz * (m3yx * zu - m3zx * yu ) +
xu * (m3yx * m3zz - m3zx * m3yz) )) / det;
v[2] = w3cz + ((m3xx * (m3yy * zu - m3zy * yu ) -
m3xy * (m3yx * zu - m3zx * yu ) +
xu * (m3yx * m3zy - m3zx * m3yy) )) / det;
double wx = xProj(v[0], v[1], v[2]);
double wy = yProj(v[0], v[1], v[2]);
double wz = zProj(v[0], v[1], v[2]);
if (Math.abs (det - 1.) > 0.001) {
E.warning("rotation determinant != 1. " + det);
}
if (Math.abs (x - wx) + Math.abs (y - wy) + Math.abs (z - wz) > 0.001) {
E.info("matrix projection error: ");
E.info("original " + x + " " + y + " " + z);
E.info("deproj " + v[0] + " " + v[1] + " " + v[2]);
E.info("reproj " + wx + " " + wy + " " + wz);
}
return v;
}
public void initializeRotation (int ixcen, int iycen) {
double x = wopx(ixcen);
double y = wopy(iycen);
initializeRotation(x, y, 0.);
}
public void initializeRotationLocal(double x, double y, double z) {
// x, y, z in the local coordinates (point on the cell)
initializeRotation(xProj(x, y, z), yProj(x, y, z), zProj(x, y, z));
}
public void initializeRotation(double x, double y, double z) {
double[][] m3T = {{m3xx, m3xy, m3xz},
{m3yx, m3yy, m3yz},
{m3zx, m3zy, m3zz}};
m3B = m3T;
double[] v = deProject(x, y, z);
w2cx = x;
w2cy = y;
w2cz = 0.;
w3cx = v[0];
w3cy = v[1];
w3cz = v[2];
}
void applyRotation(double[][] mr) {
double[][] m3C = new double[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
m3C[i][j] += mr[i][k] * m3B[k][j];
}
}
}
m3xx = m3C[0][0]; m3xy = m3C[0][1]; m3xz = m3C[0][2];
m3yx = m3C[1][0]; m3yy = m3C[1][1]; m3yz = m3C[1][2];
m3zx = m3C[2][0]; m3zy = m3C[2][1]; m3zz = m3C[2][2];
if (rotationListener != null) {
rotationListener.rotationChanged();
}
}
void axisRotate (double thax, double thr) {
// rotate through angle thr about the line in the x-y plane making
// angle thax with the line y = 0;
double cf = Math.cos (thax);
double sf = Math.sin (thax);
double cr = Math.cos (thr);
double sr = Math.sin (thr);
double[][] mr = { {(cf*cf + sf*cr*sf), (cf*sf - sf*cr*cf), (-sr*sf)},
{(sf*cf - cf*cr*sf), (sf*sf + cf*cr*cf), (cf*sr)},
{(sr*sf), (-sr*cf), cr}};
applyRotation(mr);
}
public void zRotate (double theta) {
double cf = Math.cos (theta);
double sf = Math.sin (theta);
double[][] mr = { {cf, sf, 0.},
{-sf, cf, 0.},
{0., 0., 1.} };
applyRotation(mr);
}
public void printRot() {
E.info("rotmat: " + m3xx + " " + m3xy + " " + m3xz);
E.info(" " + m3yx + " " + m3yy + " " + m3yz);
E.info(" " + m3zx + " " + m3zy + " " + m3zz);
}
public void dragZRotate (int idx, int idy) {
if (m3B != null) {
double theta = idy / 60.; // ***
zRotate (theta);
}
}
public void dragRollRotate (int idx, int idy) {
if (m3B != null) {
double thax = Math.atan2(idx, idy);
double thar = Math.sqrt (idx*idx + idy*idy) / 60.; // ***
axisRotate (thax, thar);
}
}
public boolean visible3D(double x, double y, double z) {
// TODO Auto-generated method stub
return (Math.abs (1.5 * dpdwx * (xProj(x,y,z) - wcx)) < canvasWidth &&
Math.abs (1.5 * dpdwy * (yProj(x,y,z) - wcy)) < canvasHeight);
}
public double[][] getProjectionMatrix() {
double[][] mat = {{m3xx, m3xy, m3xz}, {m3yx, m3yy, m3yz}, {m3zx, m3zy, m3zz}};
return mat;
}
public double[] get3Center() {
double[] ret = {w3cx, w3cy, w3cz};
return ret;
}
public double[] get2Center() {
double[] ret = {w2cx, w2cy, w2cz};
return ret;
}
public void setProjectionMatrix(double[][] pm) {
m3xx = pm[0][0];
m3xy = pm[0][1];
m3xz = pm[0][2];
m3yx = pm[1][0];
m3yy = pm[1][1];
m3yz = pm[1][2];
m3zx = pm[2][0];
m3zy = pm[2][1];
m3zz = pm[2][2];
}
public void set3Center(double[] cen) {
w3cx = cen[0];
w3cy = cen[1];
w3cz = cen[2];
}
public void set2Center(double[] cen) {
w2cx = cen[0];
w2cy = cen[1];
}
public void setScale(double sf) {
dpdwx = sf;
dpdwy = sf;
}
public double getScale() {
return Math.sqrt(dpdwx * dpdwy);
}
}
/*
*
*
*
* public final double[] limits() { return getRange(); }
*
* public final double[] getLimits () { double[] da = getRange(); double[] ada =
* new double[4]; for (int i = 0; i < 4; i++) ada[i] = Math.abs (da[i]); double
* xm = (ada[1] > ada[0] ? ada[1] : ada[0]); double ym = (ada[3] > ada[2] ?
* ada[3] : ada[2]); int px = (int) ((Math.log (xm) / - Math.log (Math.abs
* (da[1] - da[0]))) / Math.log(10.)) + 3; int py = (int) ((Math.log (ym) / -
* Math.log (Math.abs (da[3] - da[2]))) / Math.log(10.)) + 3; da[0] =
* Formatter.trim (da[0], px); da[1] = Formatter.trim (da[1], px); da[2] =
* Formatter.trim (da[2], py); da[3] = Formatter.trim (da[3], py); return da; }
*
*
* public final double[] alims (double[] x, int n) { double a = x[0]; double b =
* x[0]; for (int i = 0; i < n; i++) { if (x[i] < a) a = x[i]; if (x[i] > b) b =
* x[i]; } if (a >= b) { a -= 0.5; b += 0.5; } double[] d = {a, b}; return d; }
*
* public final void setRangeToFrameData (double[] x, double[] y, int n) {
* double[] dx = alims (x, n); double[] dy = alims (y, n); setLimits (dx[0],
* dx[1], dy[0], dy[1]); }
*
*
* } }
*
*
*
*
* public final void forceLimits (double xl, double xh, double yl, double yh) {
* if (xl > xh) { double t = xl; xl = xh; xh = t; } if (yl > yh) { double t =
* yl; yl = yh; yh = t; }
*
* boolean bxr = xRescalable; xRescalable = true; boolean byr = yRescalable;
* yRescalable = true;
*
* setXrange (xl, xh); setYrange (yl, yh); xRescalable = bxr; yRescalable = byr;
* if (constantAspectRatio) enforceAspectRatioY(); }
*
*
* public final void setLimits (double[] dd) { if (dd == null || dd.length < 4)
* return; setLimits (dd[0], dd[1], dd[2], dd[3]); } public final void
* forceLimits (double[] dd) { if (dd == null || dd.length < 4) return;
* forceLimits (dd[0], dd[1], dd[2], dd[3]); }
*
* // NB following section contains only occurences of dpdwx
*
*
*
* public final void recordLimits () { double[] bufl = new double[4]; for (int i =
* 0; i < 4; i++) bufl[i] = lastLimits[i];
*
* lastLimits[0] = wcx - hx / dpdwx; lastLimits[1] = wcx + hx / dpdwx;
* lastLimits[2] = wcy - hy / dpdwy; lastLimits[3] = wcy + hy / dpdwy;
* }
*
*
*
* public final void gdcSetSize (int w, int h) { width = w; height = h; hx =
* (width - leftMargin - rightMargin) / 2; hy = (height - topMargin -
* bottomMargin) / 2; if (hx < 2) hx = 2; if (hy < 2) hy = 2;
*
* pcx = leftMargin + hx; pcy = bottomMargin + hy; }
*
* }
*
*/