327 lines
10 KiB
Plaintext
327 lines
10 KiB
Plaintext
|
|
/*
|
||
|
|
AwtMetrics.java
|
||
|
|
*
|
||
|
|
* Copyright (c) 2000, Ted Nelson and Tuomas Lukka
|
||
|
|
*
|
||
|
|
* You may use and distribute under the terms of either the GNU Lesser
|
||
|
|
* General Public License, either version 2 of the license or,
|
||
|
|
* at your choice, any later version. Alternatively, you may use and
|
||
|
|
* distribute under the terms of the XPL.
|
||
|
|
*
|
||
|
|
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
|
||
|
|
* the licenses.
|
||
|
|
*
|
||
|
|
* 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 README
|
||
|
|
* file for more details.
|
||
|
|
*
|
||
|
|
*/
|
||
|
|
/*
|
||
|
|
* Written by Kimmo Wideroos
|
||
|
|
*/
|
||
|
|
|
||
|
|
package org.gzigzag.module;
|
||
|
|
import org.gzigzag.*;
|
||
|
|
import java.util.*;
|
||
|
|
import java.awt.*;
|
||
|
|
|
||
|
|
/** Abstract class for different metrics (in order to get different
|
||
|
|
* focus+context effects)
|
||
|
|
*/
|
||
|
|
|
||
|
|
public abstract class AwtMetrics extends ZObCellRepr implements ZOb {
|
||
|
|
public static boolean dbg = true;
|
||
|
|
static void p(String s) { if(dbg) System.out.println(s); }
|
||
|
|
static void pa(String s) { System.out.println(s); }
|
||
|
|
|
||
|
|
STRUCTPARAMS {
|
||
|
|
int[] RealView
|
||
|
|
= { 400, 400 };
|
||
|
|
|
||
|
|
int[] VirtualView
|
||
|
|
= { 400, 400 };
|
||
|
|
|
||
|
|
double[] Origo
|
||
|
|
= { 0.0, 0.0 };
|
||
|
|
|
||
|
|
int[] FocusOrigo
|
||
|
|
= { 200, 200 };
|
||
|
|
|
||
|
|
boolean GridOn
|
||
|
|
= true;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
static ZZCell FocusedCell = null;
|
||
|
|
|
||
|
|
double FocusCoefficient = focusCoefficientMinimum();
|
||
|
|
|
||
|
|
abstract double focusCoefficientMinimum();
|
||
|
|
abstract double focusCoefficientMaximum();
|
||
|
|
|
||
|
|
public double[] RealViewd() {
|
||
|
|
return new double[] { (double)RealView[0], (double)RealView[1] };
|
||
|
|
}
|
||
|
|
|
||
|
|
public double[] RealViewHalfd() {
|
||
|
|
return new double[] { (double)RealView[0]*0.5, (double)RealView[1]*0.5 };
|
||
|
|
}
|
||
|
|
|
||
|
|
public void setRealView(int x, int y, boolean adjustFocus) {
|
||
|
|
if(adjustFocus) {
|
||
|
|
double[] rvd = RealViewd();
|
||
|
|
double newfox = ((double)(x*FocusOrigo[0]))/rvd[0];
|
||
|
|
double newfoy = ((double)(y*FocusOrigo[1]))/rvd[1];
|
||
|
|
setFocusOrigo((int)newfox, (int)newfoy);
|
||
|
|
}
|
||
|
|
RealView[0] = x; RealView[1] = y;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void setRealView(Dimension d, boolean adjustFocus) {
|
||
|
|
setRealView(d.width, d.height, adjustFocus);
|
||
|
|
}
|
||
|
|
public double[] VirtualViewd() {
|
||
|
|
return new double[] { (double)VirtualView[0], (double)VirtualView[1] };
|
||
|
|
}
|
||
|
|
|
||
|
|
public double[] VirtualViewHalfd() {
|
||
|
|
return new double[] { (double)VirtualView[0]*0.5, (double)VirtualView[1]*0.5 };
|
||
|
|
}
|
||
|
|
|
||
|
|
public void setVirtualView(int x, int y) {
|
||
|
|
VirtualView[0] = x; VirtualView[1] = y;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void setOrigo(double ox, double oy) {
|
||
|
|
Origo[0] = ox;
|
||
|
|
Origo[1] = oy;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void moveOrigo(double dox, double doy) {
|
||
|
|
Origo[0] += dox;
|
||
|
|
Origo[1] += doy;
|
||
|
|
}
|
||
|
|
|
||
|
|
public double[] FocusOrigod() {
|
||
|
|
return new double[] { (double)FocusOrigo[0], (double)FocusOrigo[1] };
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public void setFocusOrigo(int fox, int foy) {
|
||
|
|
setFocusOrigo(fox, foy, null);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void setFocusOrigo(int fox, int foy, ZZCell focusCell) {
|
||
|
|
FocusOrigo[0] = fox;
|
||
|
|
FocusOrigo[1] = foy;
|
||
|
|
if(focusCell != null && focusCell == FocusedCell) {
|
||
|
|
FocusCoefficient += 1.0;
|
||
|
|
if(FocusCoefficient > focusCoefficientMaximum())
|
||
|
|
FocusCoefficient = focusCoefficientMaximum();
|
||
|
|
} else {
|
||
|
|
FocusCoefficient = focusCoefficientMinimum();
|
||
|
|
FocusedCell = focusCell;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public void init(ZZCell start, Dimension rv, Dimension vv,
|
||
|
|
double ox, double oy) {
|
||
|
|
setCell(start);
|
||
|
|
setRealView(rv.width, rv.height, false);
|
||
|
|
setVirtualView(vv.width, vv.height);
|
||
|
|
setOrigo(ox, oy);
|
||
|
|
setFocusOrigo(rv.width>>1, rv.height>>1);
|
||
|
|
}
|
||
|
|
|
||
|
|
public AwtMetrics() { }
|
||
|
|
|
||
|
|
public AwtMetrics(ZZCell start, Dimension rv, Dimension vv,
|
||
|
|
double ox, double oy)
|
||
|
|
{
|
||
|
|
init(start, rv, vv, ox, oy);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
private Point mapToUnfocusedRealView(double x, double y) {
|
||
|
|
int rx, ry;
|
||
|
|
double[] vvhd = VirtualViewHalfd(), rvhd = RealViewHalfd();
|
||
|
|
rx = (int)(( (x-Origo[0]) * vvhd[0]) + rvhd[0]);
|
||
|
|
ry = (int)(( (y-Origo[1]) * vvhd[1]) + rvhd[1]);
|
||
|
|
return new Point(rx, ry);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** mapping from 'virtualview' (=modelview, coordinates
|
||
|
|
* -1.0<x,y<1.0) to 'realview' (coordinates in this.RealView).
|
||
|
|
* can be used for example in order to gain an illusion of focus+context
|
||
|
|
* by demagnifying areas near focus. ceturns 'realview' coordinates.
|
||
|
|
* @param x x-coordinate ranging from -infinity ... infinity
|
||
|
|
* @param y y-coordinate
|
||
|
|
*/
|
||
|
|
public Point mapToRealView(double x, double y) {
|
||
|
|
Point ufr; // unfocused realview point
|
||
|
|
ufr = mapToUnfocusedRealView(x, y);
|
||
|
|
return focusRealView(ufr.x, ufr.y);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** reverse mapping, see 'mapToRealView' */
|
||
|
|
public double[] mapToVirtualView(int rx, int ry) {
|
||
|
|
double x, y;
|
||
|
|
double[] vvhd = VirtualViewHalfd(), rvhd = RealViewHalfd();
|
||
|
|
Point iCoord = inverseTransform(rx, ry);
|
||
|
|
x = (((double)iCoord.x - rvhd[0]) / vvhd[0]) + Origo[0];
|
||
|
|
y = (((double)iCoord.y - rvhd[1]) / vvhd[1]) + Origo[1];
|
||
|
|
return new double[] { x, y };
|
||
|
|
}
|
||
|
|
|
||
|
|
public Point mapToRealView(double[] coord) {
|
||
|
|
return mapToRealView(coord[0], coord[1]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public Point focusRealView(int x, int y) {
|
||
|
|
double xFocus, yFocus, dx, dy;
|
||
|
|
double[] d;
|
||
|
|
double[] vvhd = VirtualViewHalfd();
|
||
|
|
xFocus = (double)(x - FocusOrigo[0]);
|
||
|
|
yFocus = (double)(y - FocusOrigo[1]);
|
||
|
|
d = transformAtFocusNbhood(xFocus/vvhd[0], yFocus/vvhd[1]);
|
||
|
|
return new Point(FocusOrigo[0]+(int)(vvhd[0]*d[0]), FocusOrigo[1]+(int)(vvhd[1]*d[1]));
|
||
|
|
}
|
||
|
|
|
||
|
|
public Point inverseTransform(int x, int y) {
|
||
|
|
double xFocus, yFocus, dx, dy;
|
||
|
|
double[] d;
|
||
|
|
double[] vvhd = VirtualViewHalfd();
|
||
|
|
xFocus = (double)(x - FocusOrigo[0]);
|
||
|
|
yFocus = (double)(y - FocusOrigo[1]);
|
||
|
|
d = inverseTransformAtFocusNbhood(xFocus/vvhd[0], yFocus/vvhd[1]);
|
||
|
|
return new Point(FocusOrigo[0]+(int)(vvhd[0]*d[0]), FocusOrigo[1]+(int)(vvhd[1]*d[1]));
|
||
|
|
}
|
||
|
|
|
||
|
|
public double[] getVirtualDimension(int x, int y, Dimension dim) {
|
||
|
|
double s = getInverseScalingValue(x, y);
|
||
|
|
double[] vvhd = VirtualViewHalfd();
|
||
|
|
return new double[] {s*(double)dim.width/vvhd[0], s*(double)dim.height/vvhd[1]};
|
||
|
|
}
|
||
|
|
|
||
|
|
public Dimension getRealDimension(double x, double y, double[] dim) {
|
||
|
|
double s = getScalingValue(x, y);
|
||
|
|
double[] vvhd = VirtualViewHalfd();
|
||
|
|
return new Dimension((int)(s*(double)dim[0]*vvhd[0]), (int)(s*(double)dim[1]*vvhd[1]));
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
abstract public double[] transformAtFocusNbhood(double x, double y,
|
||
|
|
double focusCoeff);
|
||
|
|
|
||
|
|
abstract public double[] inverseTransformAtFocusNbhood(double x, double
|
||
|
|
y, double focusCoeff);
|
||
|
|
|
||
|
|
abstract public double transformScalingValue(double s);
|
||
|
|
|
||
|
|
|
||
|
|
public double[] transformAtFocusNbhood(double x, double y) {
|
||
|
|
return transformAtFocusNbhood(x, y, FocusCoefficient);
|
||
|
|
}
|
||
|
|
|
||
|
|
public double[] inverseTransformAtFocusNbhood(double x, double y) {
|
||
|
|
return inverseTransformAtFocusNbhood(x, y, FocusCoefficient);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public double getScalingValue(double x, double y) {
|
||
|
|
double d1x, d1y, d2x, d2y, s;
|
||
|
|
|
||
|
|
Point ufr, invf; // unfocused realview point, inverse focus point
|
||
|
|
Point rPoint = mapToRealView(x, y);
|
||
|
|
|
||
|
|
d1x = (double)(rPoint.x-FocusOrigo[0]);
|
||
|
|
d1y = (double)(rPoint.y-FocusOrigo[1]);
|
||
|
|
|
||
|
|
ufr = mapToUnfocusedRealView(x, y);
|
||
|
|
invf = inverseTransform(FocusOrigo[0], FocusOrigo[1]);
|
||
|
|
|
||
|
|
d2x = (double)(ufr.x-invf.x);
|
||
|
|
d2y = (double)(ufr.y-invf.y);
|
||
|
|
|
||
|
|
s = Math.sqrt((d1x*d1x + d1y*d1y)/(d2x*d2x + d2y*d2y));
|
||
|
|
|
||
|
|
return transformScalingValue(s);
|
||
|
|
}
|
||
|
|
|
||
|
|
public double getInverseScalingValue(int rx, int ry) {
|
||
|
|
double d1x, d1y, d2x, d2y, s;
|
||
|
|
Point ufr, invf; // unfocused realview point, inverse focus point
|
||
|
|
|
||
|
|
d1x = rx-FocusOrigo[0];
|
||
|
|
d1y = ry-FocusOrigo[1];
|
||
|
|
|
||
|
|
ufr = inverseTransform(rx, ry);
|
||
|
|
invf = inverseTransform(FocusOrigo[0], FocusOrigo[1]);
|
||
|
|
|
||
|
|
d2x = (double)(ufr.x-invf.x);
|
||
|
|
d2y = (double)(ufr.y-invf.y);
|
||
|
|
|
||
|
|
s = Math.sqrt((d2x*d2x + d2y*d2y)/(d1x*d1x + d1y*d1y));
|
||
|
|
|
||
|
|
return transformScalingValue(s);
|
||
|
|
}
|
||
|
|
|
||
|
|
public boolean RealViewEquals(Dimension view) {
|
||
|
|
if(view.width==RealView[0] && view.height==RealView[1])
|
||
|
|
return true;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Write the parameters of this ZOb back in the cellstructure.
|
||
|
|
* Returns a string describing the errors encountered, or null if
|
||
|
|
* everything went fine..
|
||
|
|
* @param c starting cell
|
||
|
|
* @param clone whether or not to make the new ZOb centralcell a clone
|
||
|
|
* of the former centralcell (if cells equal, the whole
|
||
|
|
* issue is trivial).
|
||
|
|
*/
|
||
|
|
|
||
|
|
String cellRepr(ZZCell start, boolean clone) {
|
||
|
|
ZZCell c2, c = start.getOrNewCell("d.1");
|
||
|
|
start.setText(getZObName());
|
||
|
|
c.setText(getZObClassName());
|
||
|
|
c = c2 = c.getOrNewCell("d.1");
|
||
|
|
c.setText("RealView");
|
||
|
|
c = c.getOrNewCell("d.1");
|
||
|
|
c.setText(""+RealView[0]);
|
||
|
|
c = c.getOrNewCell("d.1");
|
||
|
|
c.setText(""+RealView[1]);
|
||
|
|
|
||
|
|
c = c2 = c2.getOrNewCell("d.2");
|
||
|
|
c.setText("VirtualView");
|
||
|
|
c = c.getOrNewCell("d.1");
|
||
|
|
c.setText(""+VirtualView[0]);
|
||
|
|
c = c.getOrNewCell("d.1");
|
||
|
|
c.setText(""+VirtualView[1]);
|
||
|
|
|
||
|
|
c = c2 = c2.getOrNewCell("d.2");
|
||
|
|
c.setText("Origo");
|
||
|
|
c = c.getOrNewCell("d.1");
|
||
|
|
c.setText(""+Origo[0]);
|
||
|
|
c = c.getOrNewCell("d.1");
|
||
|
|
c.setText(""+Origo[1]);
|
||
|
|
|
||
|
|
c = c2 = c2.getOrNewCell("d.2");
|
||
|
|
c.setText("FocusOrigo");
|
||
|
|
c = c.getOrNewCell("d.1");
|
||
|
|
c.setText(""+FocusOrigo[0]);
|
||
|
|
c = c.getOrNewCell("d.1");
|
||
|
|
c.setText(""+FocusOrigo[1]);
|
||
|
|
|
||
|
|
c = c2 = c2.getOrNewCell("d.2");
|
||
|
|
c.setText("GridOn");
|
||
|
|
c = c.getOrNewCell("d.1");
|
||
|
|
c.setText(""+GridOn);
|
||
|
|
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|