Files
secondo/Javagui/viewer/hoese/algebras/Dsplhistogram2d.java

1351 lines
57 KiB
Java
Raw Normal View History

2026-01-23 17:03:45 +08:00
//This file is part of SECONDO.
//Copyright (C) 2004, University in Hagen, Department of Computer Science,
//Database Systems for New Applications.
//SECONDO is free software; you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation; either version 2 of the License, or
//(at your option) any later version.
//SECONDO 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 General Public License for more details.
//You should have received a copy of the GNU General Public License
//along with SECONDO; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package viewer.hoese.algebras;
import java.awt.geom.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.font.*;
import java.awt.image.*;
import java.lang.Math;
import sj.lang.ListExpr;
import java.util.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JFileChooser;
import viewer.*;
import viewer.hoese.*;
import tools.Reporter;
import gui.SecondoObject;
import gui.idmanager.ID;
import viewer.Viewer3D;
import viewer.viewer3d.graphic2d.Figure2D;
import viewer.viewer3d.graphic2d.IDPoint2D;
import viewer.viewer3d.graphic2d.Triangle2D;
import viewer.viewer3d.graphic3d.*;
import viewer.viewer3d.objects.*;
//import viewer.viewer3d.graphic2d.Point2D;
/**
* A Displayclass for an graph from the histogram2d-algebra
*/
public class Dsplhistogram2d extends DsplGeneric implements ExternDisplay
{
/** The internal datatype representation */
static ExtWin extWin = new ExtWin("Histogram2D");
static double[] rangesXVec = null;
static double[] rangesZVec = null;
static double[] binsVec = null;
static double[] rangesXVecOld = null;
static double[] rangesZVecOld = null;
static double[] binsVecOld = null;
boolean undef = false;
boolean err;
// Rectangle2D.Double bounds=null;
static ID id = new ID();
/**
* Scans the numeric representation of a histogram2d datatype
*
* @param v
* the nestedlist representation of the histogram
* ((rangeX*)(rangeY*)(bin*))
*/
protected void ScanValue(ListExpr v)
{
int i = 0; //for rangesX
int k = 0; //for rangesY
int j = 0; //for bins
int c = 0; //size rangesXVec
int d = 0; //size rangesYVec
if ( isUndefined(v) ){
undef = true;
return;
}
if(v.listLength()!=3){
Reporter.writeError("ListLength of the graph type must be two.");
err=true;
return;
}
// ListExpr rangesX = v.first();
// ListExpr rangesZ = v.second();
ListExpr rangesZ = v.first();
ListExpr rangesX = v.second();
ListExpr bins = v.third();
ListExpr rangesXRest = rangesX;
ListExpr rangesZRest = rangesZ;
ListExpr binsRest = bins;
ListExpr rangesXCount = rangesX;
ListExpr rangesZCount = rangesZ;
// ListExpr binsCount = bins;
if(((rangesX.listLength()-1) * (rangesZ.listLength()-1)) != ( bins.listLength()) ){
Reporter.writeError("Incorrect data format!");
err=true;
return;
}
while (!rangesXCount.isEmpty())
{
c++;
rangesXCount = rangesXCount.rest();
}
while (!rangesZCount.isEmpty())
{
d++;
rangesZCount = rangesZCount.rest();
}
this.binsVecOld = binsVec; //copy of ranges and bins to hold old data for second panel
this.rangesXVecOld = rangesXVec;
this.rangesZVecOld = rangesZVec;
rangesXVec = new double[c];
rangesZVec = new double[d];
int binCount = (c-1) * (d-1);
binsVec = new double[binCount];
while (!rangesXRest.isEmpty())
{
ListExpr rangeX = rangesXRest.first();
if(rangesXRest.first().atomType()!=ListExpr.REAL_ATOM){
Reporter.writeError("invalid representation of a range found");
return;
}
double rangeXD = rangeX.realValue();
// System.out.println(" rangeXD: " + rangeXD);
rangesXVec[i] = rangeXD;
rangesXRest = rangesXRest.rest();
i++;
}
while (!rangesZRest.isEmpty())
{
ListExpr rangeY = rangesZRest.first();
if(rangesZRest.first().atomType()!=ListExpr.REAL_ATOM){
Reporter.writeError("invalid representation of a range found");
return;
}
double rangeZD = rangeY.realValue();
// System.out.println(" rangeYD: " + rangeZD);
rangesZVec[k] = rangeZD;
rangesZRest = rangesZRest.rest();
k++;
}
while (!binsRest.isEmpty())
{
ListExpr bin = binsRest.first();
if( binsRest.first().atomType()!=ListExpr.REAL_ATOM ){
Reporter.writeError("invalid representation of a bin found");
err=true;
return;
}
double binD = bin.realValue();
// System.out.println(" binD: " + binD);
binsVec[j] = binD;
binsRest = binsRest.rest();
j++;
}
// System.out.println("ich bin durch im ScanValue!");
}
/**
* Init. the Dsplhistogram2d instance.
*
* @param type
* The symbol histogram2d
* @param value
* the nestedlist representation of the histogram2d
* @param qr
* queryresult to display output.
*/
public void init(String name, int nameLength, int indent, ListExpr type,
ListExpr value, QueryResult qr){
AttrName = extendString(name, nameLength, indent);
ScanValue(value);
if(undef){
qr.addEntry(new String(AttrName + ": undefined"));
return;
}
if (err){
Reporter.writeError("Error in ListExpr :parsing aborted");
qr.addEntry(new String("(" + AttrName + ": GA(graph))"));
return;
} else{
qr.addEntry(this);
// extWin.setVisible(true); //!!!GLEICH AM ANFANG FENSTER OFFEN
}
}
/**
* shows this histogram in an external window
*/
public void displayExtern(){
extWin.setSource(this);
extWin.setVisible(true);
}
public boolean isExternDisplayed(){
return this== extWin.hist2d && extWin.isVisible();
}
// ####################### E X T E R N W I N D O W ##################################
/**
* to show the histograms in an external window
*/
private static class ExtWin extends JFrame{
private MyWorld3D w3dPanel1;
private MyWorld3D w3dPanel2;
public Dsplhistogram2d hist2d = null;
/** creates a new external window **/
public ExtWin(String title){
super(title);
JPanel showPanel = new JPanel( (new GridLayout(1,2)));
w3dPanel1 = new MyWorld3D();
showPanel.add(w3dPanel1);
w3dPanel2 = new MyWorld3D();
showPanel.add(w3dPanel2);
// int panelWidth = 350;
// int panelHeight = 550;
//to conform panel size to histogram2d
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension screenSize = toolkit.getScreenSize();
int size = Math.min(screenSize.width/2, screenSize.height);
w3dPanel1.setPreferredSize(new Dimension(size-40, size-40));
w3dPanel2.setPreferredSize(new Dimension(size-40, size-40));
MouseNavigator mouseNavi = new MouseNavigator();
w3dPanel1.addMouseListener(mouseNavi);
w3dPanel1.addMouseWheelListener(mouseNavi);
w3dPanel1.addMouseMotionListener(mouseNavi);
w3dPanel2.addMouseListener(mouseNavi);
w3dPanel2.addMouseWheelListener(mouseNavi);
w3dPanel2.addMouseMotionListener(mouseNavi);
mouseNavi.addViewReceiver(w3dPanel1);
mouseNavi.addViewReceiver(w3dPanel2);
mouseNavi.updateViewReceivers();//starting position
// w3dPanel1.setKeyListener();
// w3dPanel2.setKeyListener();
this.validate();
getContentPane().setLayout(new BorderLayout());
getContentPane().add(showPanel,BorderLayout.CENTER);
JPanel p2 = new JPanel();
JButton saveLeft = new JButton("save left");
saveLeft.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent evt){
JFileChooser fc = new JFileChooser(".");
if(fc.showSaveDialog(null)==JFileChooser.APPROVE_OPTION){
//System.out.println(" PSEXPORT >>> ");
extern.psexport.PSCreator.export(w3dPanel1,fc.getSelectedFile());
//System.out.println("PSEXPORT <<<<");
}
}
});
p2.add(saveLeft);
getContentPane().add(p2,BorderLayout.SOUTH);
this.pack();
}
public void setSource(Dsplhistogram2d hist2d){
this.hist2d = hist2d;
this.w3dPanel1.setHistogram(hist2d.rangesXVec, hist2d.rangesZVec, hist2d.binsVec);
this.w3dPanel2.setHistogram(hist2d.rangesXVecOld,hist2d.rangesZVecOld, hist2d.binsVecOld);
}
}
//############################## M O U S E N A V I G A T O R ##########################
/**
* to scoll in the scene and to switch the view of the scene by the mouse
*/
public static class MouseNavigator extends MouseAdapter implements MouseWheelListener, MouseMotionListener{
private static final double zoomStep = 0.05;
/**count of complete rotations for moving the mouse one pixel*/
private static final double rotationSpeed = 0.001;
private Vector w3ds;
private int mousePressedBeginX = 0;
private int mousePressedBeginY = 0;
/**the angle in the x-z plane starting at z and rotation counterclockwise (to positive x)*/
private double theta = 35.0/360.0*2*Math.PI;
/**the angle starting at 0 = y-axis and leading to x-z plane*/
private double phi = 75.0/360.0*2*Math.PI;
private double zoomFactor = 1.0;
private double thetaAtDragStart = theta;
private double phiAtDragStart = phi;
public MouseNavigator(){
this.w3ds = new Vector();
}
/**
* @param receiver all added receivers will have set their view (camera)
*/
public void addViewReceiver(World3D receiver){
this.w3ds.add(receiver);
}
public void mouseWheelMoved(MouseWheelEvent e) {
if (e.getWheelRotation() > 0){
zoomFactor *= (1.0+zoomStep);
}
else{
zoomFactor /= (1.0+zoomStep);
}
this.updateViewReceivers();
}
public void mousePressed(MouseEvent e){
mousePressedBeginX = e.getX();
mousePressedBeginY = e.getY();
Iterator it = this.w3ds.iterator();
while (it.hasNext()){
MyWorld3D w3d = (MyWorld3D)(it.next());
w3d.grabFocus();
w3d.repaint();
}
}
public void mouseReleased(MouseEvent e){
thetaAtDragStart = theta;
phiAtDragStart = phi;
}
public void mouseDragged(MouseEvent e){
int mouseX = e.getX() - this.mousePressedBeginX;//relative position
int mouseY = e.getY() - this.mousePressedBeginY;
this.theta = this.thetaAtDragStart - mouseX*2*Math.PI*rotationSpeed;
this.phi = this.phiAtDragStart - mouseY*2*Math.PI*rotationSpeed;
//clamp phi inside interval of 5 degree and 175 degree to avoid gimbal lock
if (this.phi < 5.0/360.0*2*Math.PI){
this.phi = 5.0/360.0*2*Math.PI;
}
else if (this.phi > 175.0/360.0*2*Math.PI){
this.phi = 175.0/360.0*2*Math.PI;
}
this.updateViewReceivers();
}
public void mouseMoved(MouseEvent arg0) {}
public void updateViewReceivers(){
// System.out.println("im updateViewRecivers 1");
//theta, phi, and zoomFactor are ready
double camera_X_OnUnitCircle = Math.sin(this.theta)*Math.sin(this.phi)*this.zoomFactor;
double camera_Y_OnUnitCircle = Math.cos(this.phi)*this.zoomFactor;
double camera_Z_OnUnitCircle = Math.sin(phi)*Math.cos(this.theta)*this.zoomFactor;
Iterator it = this.w3ds.iterator();
while (it.hasNext()){
MyWorld3D w3d = (MyWorld3D)(it.next());
double cameraDistance = w3d.cameraDistance;
// System.out.println("updateViewReceiver");
w3d.setView(camera_X_OnUnitCircle*cameraDistance+w3d.cameraTargetX,
camera_Y_OnUnitCircle*cameraDistance+w3d.cameraTargetY,
camera_Z_OnUnitCircle*cameraDistance+w3d.cameraTargetZ,
w3d.cameraTargetX, w3d.cameraTargetY, w3d.cameraTargetZ, 0, 1000, 0);
double windowSize = (cameraDistance*this.zoomFactor);
w3d.setWindow(windowSize, windowSize);
w3d.validate();
w3d.update();
w3d.repaint();
}
// System.out.println("im updateViewRecivers end");
}
}
//####################################################################################################################
/**
* to form my own World3D with its camera position, its ranges and bins and its mouse navigator
* to write the paint method for MyWorld3D
*/
private static class MyWorld3D extends World3D{
double[] rangesXVecPaint = null;
double[] rangesZVecPaint = null;
double[] binsVecPaint = null;
double[] binsHeightPaint = null;
private Color mainColor = Color.white;
MouseNavigator mouseNavi = new MouseNavigator();
private static Stroke stroke = new BasicStroke(0.5f);
int selectedBin = -1;
public double cameraDistance = 250;
public double cameraTargetX = 0;//point where the camera looks at
public double cameraTargetY = 0;
public double cameraTargetZ = 0;
//to paint the coordinates
public void paint(Graphics g){
((Graphics2D)g).setStroke(stroke);
//System.out.println("im paint 1");
try{
super.paint(g);
} catch(Exception e ){
Reporter.debug(e);;
}
// System.out.println("im paint 2");
if (this.rangesXVecPaint == null || this.rangesZVecPaint == null || this.binsHeightPaint == null){
// no information
//System.err.println("im paint 3");
//System.err.println("rangesXVecPaint = " + rangesXVecPaint);
//System.err.println("rangesZVecPaint = " + rangesZVecPaint);
// System.err.println("binsHeightPaint = " + binsHeightPaint);
return;
}
else{
// System.out.println("im paint 4");
FM3DGraphic Fm3D = new FM3DGraphic();
try {
Fm3D.setView(this.getEyeX(), this.getEyeY(), this.getEyeZ(),
this.getVRPX(), this.getVRPY(), this.getVRPZ(),
this.getViewUpX(), this.getViewUpY(), this.getViewUpZ());
} catch (Exception e) {
e.printStackTrace();
}
Fm3D.setWindow(this.getWindowX(), this.getWindowY());
int min = Math.min(this.getWidth(),this.getHeight());
Fm3D.setViewport(10,10,min-20,min-20);
//Fm3D ready to transform
// System.out.println("im paint 5");
double minX = rangesXVecPaint[0];
double maxX = rangesXVecPaint[rangesXVecPaint.length-1];
double minZ = rangesZVecPaint[0];
double maxZ = rangesZVecPaint[rangesZVecPaint.length-1];
double maxY = this.getMax(this.binsHeightPaint);
double minY = this.getMin(this.binsHeightPaint);
double minXsmaller0;
double minYsmaller0;
double minZsmaller0;
if (minY == 0.0 && maxY == 0.0){
maxY = 10.0;
}
if(minX > 0.0){
minXsmaller0 = 0.0;
}
else {
minXsmaller0 = minX;
}
if(minY > 0.0){
minYsmaller0 = 0.0;
}
else {
minYsmaller0 = minY;
}
if(minX > 0.0){
minZsmaller0 = 0.0;
}
else {
minZsmaller0 = minZ;
}
// System.out.println("im paint 7");
double unitX = 100/(Math.abs(maxX)+ Math.abs(minXsmaller0)); //units to paint in the panel
double unitY = 100/(Math.abs(maxY)+ Math.abs(minYsmaller0));
double unitZ = 100/(Math.abs(maxZ)+ Math.abs(minZsmaller0));
Vector stepsX = this.paintSteps(maxX, minX);
Vector stepsZ = this.paintSteps(maxZ, minZ);
Vector stepsHeight = this.paintSteps(maxY, minY);
Iterator itx = stepsX.iterator();
int i = 0;
if(minX > 0.0){
minX = 0.0;
}
if(minZ > 0.0){
minZ = 0.0;
}
g.setFont((new Font("Helvetica", Font.PLAIN, 9)));
while (itx.hasNext() ){
//x vary *unitX
//z = 0
//y = 0
double itxNext = ((Double)(itx.next())).doubleValue();
String itxNextStr = Double.toString(itxNext);
String itxNextStrShort = itxNextStr.substring(0, Math.min(itxNextStr.length(),itxNextStr.indexOf(".")+3));
Point transformed = this.transformPoint((maxX-itxNext)*unitX, 0, (maxZ-minZ)*unitZ, Fm3D);
if (transformed != null){
g.drawString(itxNextStrShort, transformed.x-15, transformed.y+15);
}
i++;
}
Iterator itz = stepsZ.iterator();
int j = 0;
// System.out.println("im paint 8");
while (itz.hasNext() ){
//x = 0
//z vary *unitZ
//y = 0
double itzNext = ((Double)(itz.next())).doubleValue();
String itzNextStr = Double.toString(itzNext);
String itzNextStrShort = itzNextStr.substring(0, Math.min(itzNextStr.length(),itzNextStr.indexOf(".")+3));
Point transformed = this.transformPoint((maxX-minX)*unitX,0,(maxZ-itzNext)*unitZ, Fm3D);
if (transformed != null){
g.drawString(itzNextStr, transformed.x+5, transformed.y+10);
}
j++;
}
//maximal z coordinate
String maxZstr = Double.toString(maxZ);
String maxZShort = maxZstr.substring(0, Math.min(maxZstr.length(),maxZstr.indexOf(".")+3));
Point transformedZ = this.transformPoint((maxX-minX)*unitX,0,(maxZ-maxZ)*unitZ, Fm3D);
if (transformedZ != null){
g.drawString(maxZShort, transformedZ.x+5, transformedZ.y+10);
}
Iterator itheight = stepsHeight.iterator();
int k = 0;
while (itheight.hasNext() ){
//x = 0
//z = 0
//y vary * unitY
double itheightNext = ((Double)(itheight.next())).doubleValue();
String itheightNextStr = Double.toString(itheightNext);
String itheightNextStrShort = itheightNextStr.substring(0, Math.min(itheightNextStr.length(),
itheightNextStr.indexOf(".")+3));
Point transformed = this.transformPoint(0,(itheightNext)*unitY, (maxZ-minZ)*unitZ, Fm3D);
if (transformed != null){
g.drawString(itheightNextStrShort, transformed.x-28, transformed.y+5);
}
k++;
}
//maximal height
String maxHeight = Double.toString(maxY);
String maxHeightShort = maxHeight.substring(0, Math.min(maxHeight.length(),maxHeight.indexOf(".")+3));
Point transformed = this.transformPoint(0,(maxY)*unitY, (maxZ-minZ)*unitZ, Fm3D);
if (transformed != null){
g.drawString(maxHeightShort, transformed.x-28, transformed.y+5);
}
}
// System.out.println("im paint end");
}
/**
* Transforms a 3D-point in 2D-coordinates
* @param x
* @param y
* @param z
* @param Fm3D
* @return A 2D point.
*/
private Point transformPoint(double x, double y, double z, FM3DGraphic Fm3D){
// System.out.println("im transformPoint 1");
Point3D toTransform = new Point3D(x, y, z,255,255,255,id);
Figure2D transformedFigure = toTransform.project(Fm3D);
if(transformedFigure == null){
return null;
}
if (transformedFigure instanceof IDPoint2D){
IDPoint2D transformedPoint = (IDPoint2D) transformedFigure;
return new Point((int)(transformedPoint.getX()), (int)(transformedPoint.getY()));
}
else{
// System.out.println("im transformPoint exit weil null");
return null;
}
}
/**
*
* @param targetX
* @param targetY
* @param targetZ
*/
public void setCameraTarget(double targetX, double targetY, double targetZ){
this.cameraTargetX = targetX;
this.cameraTargetY = targetY;
this.cameraTargetZ = targetZ;
}
public void setCameraDistance(double cameraDistance){
this.cameraDistance = cameraDistance;
}
/**
* sets the color of a histogram2d
*
* @param mainColor
*/
public void setMainColor(Color mainColor){
this.mainColor = mainColor;
}
/**
* computes the heights of the columns given by binAreas divided by the ranges
* @param rangesX
* @param rangesZ
* @param binAreas
* @return Array of heights to paint on y-axis.
*/
private double[] getBinHeights(double[] rangesX, double[] rangesZ, double[] binAreas)
{
// System.out.println("in getBinHeights");
double[] out = new double[binAreas.length];
int binsCount = 0;
for (int j = 0; j < rangesZ.length-1; j++){
for (int i = 0; i < rangesX.length-1; i++){
// System.out.println("rangesX["+i+"]: "+rangesX[i]);
// System.out.println("binsCount: "+binsCount);
out[binsCount] = binAreas[binsCount]/((rangesX[i+1] - rangesX[i]) * (rangesZ[j+1] - rangesZ[j]));
binsCount++;
}
}
// System.out.println("im getBinHeights 1");
return out;
}
/**
*
* @param rangesXVecPaint
* @param rangesZVecPaint
* @param binsVecPaint
*/
public void setHistogram(double[] rangesXVecPaint,double[] rangesZVecPaint, double[] binsVecPaint){
//System.out.println("im setHistogram 1");
this.removeAll();
this.rangesXVecPaint = rangesXVecPaint;
this.rangesZVecPaint = rangesZVecPaint;
this.binsVecPaint = binsVecPaint;
if (this.rangesXVecPaint == null || this.rangesZVecPaint == null || this.binsVecPaint == null){
this.binsHeightPaint = null;
this.removeID(id);
return;
}
else{
this.binsHeightPaint = this.getBinHeights(rangesXVecPaint, rangesZVecPaint, binsVecPaint);
// System.out.println("im setHistogram 2");
}
// local Data array ready
// set data 3D
//***********************************************************
double minX = rangesXVecPaint[0];
double maxX = rangesXVecPaint[rangesXVecPaint.length-1];
double minZ = rangesZVecPaint[0];
double maxZ = rangesZVecPaint[rangesZVecPaint.length-1];
double maxY = this.getMax(this.binsHeightPaint);
double minY = this.getMin(this.binsHeightPaint);
double minXsmaller0;
double minYsmaller0;
double minZsmaller0;
if (minY == 0.0 && maxY == 0.0){
maxY = 10.0;
}
if(minX > 0.0){
minXsmaller0 = 0.0;
}
else {
minXsmaller0 = minX;
}
if(minY > 0.0){
minYsmaller0 = 0.0;
}
else {
minYsmaller0 = minY;
}
if(minX > 0.0){
minZsmaller0 = 0.0;
}
else {
minZsmaller0 = minZ;
}
double unitX = 100/(Math.abs(maxX)+ Math.abs(minXsmaller0));
double unitY = 100/(Math.abs(maxY)+ Math.abs(minYsmaller0));
double unitZ = 100/(Math.abs(maxZ)+ Math.abs(minZsmaller0));
// System.out.println("minX: "+minX);
// System.out.println("maxX: "+maxX);
// System.out.println("minZ: "+minZ);
// System.out.println("maxZ: "+maxZ);
// System.out.println("minY: "+minY);
// System.out.println("maxY: "+maxY);
// System.out.println("unitX: "+unitX);
// System.out.println("unitZ: "+unitZ);
// System.out.println("unitY: "+unitY);
// System.out.println("unitX: "+unitX);
this.paintCoordinateSystemXYZ(minX, maxX, minZ, maxZ, minY, maxY, unitX, unitZ, unitY);
this.paintHistogram2d(this.rangesXVecPaint, this.rangesZVecPaint, this.binsHeightPaint, unitX, unitZ, unitY,
103, 239, 109);
// System.out.println("im setHistogram end");
this.update();
}
/**
*
* @param values
* @return Maximum of an array of doubles.
*/
private double getMax(double[] values){
// System.out.println("im getMax 1");
double out = values[0];
if (values.length == 1){
return out;
}
for (int i = 1; i < values.length; i++){
if (values[i] > out){
out = values[i];
}
}
// System.out.println("im getMax end");
return out;
}
/**
*
* @param values
* @return Minimum of an array of doubles.
*/
private double getMin(double[] values){
// System.out.println("im getMin 1");
double out = values[0];
if (values.length == 1){
return out;
}
for (int i = 1; i < values.length; i++){
if (values[i] < out){
out = values[i];
}
}
// System.out.println("im getMin end");
return out;
}
/** split the given rectangle into two triangles and inserts them into tv.
**/
private void insertRectangleSimple(Triangle3DVector tv,
Point3DSimple p1, Point3DSimple p2, Point3DSimple p3, Point3DSimple p4,
boolean l1_2, boolean l2_3, boolean l3_4, boolean l4_1,
Color borderColor, ID aID){
Triangle3D t1 = new Triangle3D(p1,p2,p3, l1_2, false,l2_3, borderColor,aID);
Triangle3D t2 = new Triangle3D(p1,p3,p4, false,l4_1,l3_4,borderColor,aID);
tv.append(t1);
tv.append(t2);
}
/** adds a rectangle to the trianglevector. The rectangle is splitted
* into nearly squares. So, the painting algorithm works better.
**/
private void insertRectangle(Triangle3DVector tv,
Point3DSimple p1, Point3DSimple p2, Point3DSimple p3, Point3DSimple p4,
Color color,
Color borderColor, ID aID){
p1.setColor(color);
p2.setColor(color);
p3.setColor(color);
p4.setColor(color);
double len1_2 = p1.distance(p2);
double len1_4 = p1.distance(p4);
if(len1_2==0 || len1_4==0){
insertRectangleSimple(tv,p1,p2,p3,p4, true,true,true,true,borderColor,aID);
} else {
double ratio = len1_2 > len1_4 ? len1_2/len1_4 : len1_4/len1_2;
if((int)ratio < 2){ // split not needed ???
insertRectangleSimple(tv,p1,p2,p3,p4, true,true,true,true,borderColor,aID);
} else {
double x1 = p1.getX();
double y1 = p1.getY();
double z1 = p1.getZ();
double x2 = p2.getX();
double y2 = p2.getY();
double z2 = p2.getZ();
double x3 = p3.getX();
double y3 = p3.getY();
double z3 = p3.getZ();
double x4 = p4.getX();
double y4 = p4.getY();
double z4 = p4.getZ();
if(len1_2>len1_4){
int steps = (int) (len1_2 / len1_4);
double dx1 = (x2-x1)/ steps;
double dx2 = (x3-x4)/steps;
double dy1 = (y2-y1)/steps;
double dy2 = (y3-y4)/steps;
double dz1 = (z2-z1)/steps;
double dz2 = (z3-z4)/steps;
Point3DSimple P1 = p1.duplicate();
Point3DSimple P4 = p4.duplicate();
for(int i=1;i<=steps;i++){
Point3DSimple P2 = new Point3DSimple(x1 + i*dx1, y1+i*dy1, z1+i*dz1,color);
Point3DSimple P3 = new Point3DSimple(x4 + i*dx2, y4+i*dy2, z4+i*dz2,color);
if(i==1){ // first rectangle
insertRectangleSimple(tv,P1,P2,P3,P4,true,false,true,true,borderColor,aID);
} else if(i==steps){ // last triangle
insertRectangleSimple(tv,P1,P2,P3,P4,true,true,true,false,borderColor,aID);
} else {
insertRectangleSimple(tv,P1,P2,P3,P4,true,false,true,false,borderColor,aID);
}
P1 = P2;
P4 = P3;
}
} else {
int steps = (int) (len1_4 / len1_2);
double dx1 = (x3-x2)/ steps;
double dx2 = (x4-x1)/steps;
double dy1 = (y3-y2)/steps;
double dy2 = (y4-y1)/steps;
double dz1 = (z3-z2)/steps;
double dz2 = (z4-z1)/steps;
Point3DSimple P1 = p2.duplicate();
Point3DSimple P4 = p1.duplicate();
for(int i=1;i<=steps;i++){
Point3DSimple P2 = new Point3DSimple( x2+i*dx1, y2+i*dy1, z2+i*dz1, color);
Point3DSimple P3 = new Point3DSimple( x1+i*dx2, y1+i*dy2 , z1+i*dz2, color);
if(i==1){ // first rectangle
insertRectangleSimple(tv,P1,P2,P3,P4,true,false,true,true,borderColor,aID);
} else if(i==steps){ // last triangle
insertRectangleSimple(tv,P1,P2,P3,P4,true,true,true,false,borderColor,aID);
} else {
insertRectangleSimple(tv,P1,P2,P3,P4,true,false,true,false,borderColor,aID);
}
P1 = P2;
P4 = P3;
}
}
}
}
}
/**
* adds the 3D geometry for one column of a histogram2d
*
* @param height
* @param rangeSmallX
* @param rangeBigX
* @param rangeSmallZ
* @param rangeBigZ
* @param cRed
* @param cGreen
* @param cBlue
*/
private void paintColumnColor(double height, double rangeSmallX, double rangeBigX, double rangeSmallZ, double rangeBigZ,
int cRed, int cGreen, int cBlue){
// System.out.println("im paintColumnColor 1");
// Point3DVector pointVecC = new Point3DVector();
// Line3DVector lineVecC = new Line3DVector();
if (height == 0.0){
return;
}
if(cRed <100){
cRed= 100;
}
if(cGreen <100){
cGreen= 100;
}
if(cBlue <100){
cBlue= 100;
}
if(cRed >205){
cRed= 205;
}
if(cGreen >205){
cGreen= 205;
}
if(cBlue >205){
cBlue= 205;
}
Color color = new Color(cRed,cGreen,cBlue);
Color borderColor = Color.BLACK;
//triangles
Point3DSimple pBackRightDownForTria = new Point3DSimple(rangeSmallX, 0, rangeBigZ,cRed,cGreen,cBlue);
Point3DSimple pBackLeftDownForTria = new Point3DSimple(rangeBigX, 0,rangeBigZ,cRed, cGreen, cBlue);
Point3DSimple pFrontRightDownForTria = new Point3DSimple(rangeSmallX, 0, rangeSmallZ,cRed, cGreen, cBlue);
Point3DSimple pFrontLeftDownForTria = new Point3DSimple(rangeBigX, 0, rangeSmallZ,cRed, cGreen, cBlue);
Point3DSimple pBackRightUpForTria = new Point3DSimple(rangeSmallX, height, rangeBigZ,cRed, cGreen, cBlue);
Point3DSimple pBackLeftUpForTria = new Point3DSimple(rangeBigX, height, rangeBigZ,cRed, cGreen, cBlue);
Point3DSimple pFrontRightUpForTria = new Point3DSimple(rangeSmallX, height, rangeSmallZ,cRed, cGreen, cBlue);
Point3DSimple pFrontLeftUpForTria = new Point3DSimple(rangeBigX, height, rangeSmallZ,cRed, cGreen, cBlue);
Triangle3DVector triaVecC = new Triangle3DVector();
// front
insertRectangle( triaVecC, pFrontLeftDownForTria, pFrontLeftUpForTria,
pFrontRightUpForTria, pFrontRightDownForTria, color, borderColor,id);
// left side
insertRectangle( triaVecC, pBackLeftDownForTria, pBackLeftUpForTria,
pFrontLeftUpForTria, pFrontLeftDownForTria, color,borderColor, id);
// back
insertRectangle( triaVecC, pBackLeftDownForTria, pBackLeftUpForTria,
pBackRightUpForTria, pBackRightDownForTria, color,borderColor, id);
// right side
insertRectangle( triaVecC, pFrontRightDownForTria, pFrontRightUpForTria,
pBackRightUpForTria, pBackRightDownForTria, color,borderColor,id);
// bottom
insertRectangle( triaVecC, pFrontLeftDownForTria, pBackLeftDownForTria,
pBackRightDownForTria, pFrontRightDownForTria, color,borderColor,id);
// top
insertRectangle( triaVecC, pFrontLeftUpForTria, pBackLeftUpForTria,
pBackRightUpForTria, pFrontRightUpForTria, color,borderColor,id);
this.add(triaVecC);
}
/**
* sets data of the histogram2d to paint
* @param _rangesX
* @param _rangesZ
* @param _bins
* @param unitX
* @param unitZ
* @param unitY
* @param cRed
* @param cGreen
* @param cBlue
*/
private void paintHistogram2d(double[] _rangesX, double[] _rangesZ, double[] _bins,double unitX,
double unitZ, double unitY, int cRed, int cGreen, int cBlue){
int binsCount = 0;
double paintX = 0.0;
double paintZ = 0.0;
double paintXplus = 0.0;
double paintZplus = 0.0;
for (int j = 0; j < _rangesZ.length-1; j++){
// System.out.println("rangesZ["+j+"]: "+_rangesZ[j]);
for (int i = 0; i < _rangesX.length-1; i++){
// System.out.println("rangesX["+i+"]: "+_rangesX[i]);
// System.out.println("binsCount: "+binsCount);
paintX = (_rangesX[_rangesX.length-1] - _rangesX[i])*unitX;
paintXplus = (_rangesX[_rangesX.length-1] - _rangesX[i+1])*unitX;
paintZ = (_rangesZ[_rangesZ.length-1] - _rangesZ[j])*unitZ;
paintZplus = (_rangesZ[_rangesZ.length-1] - _rangesZ[j+1])*unitZ;
// System.out.println("binsCount: "+binsCount);
// System.out.println("selectedBin: "+this.selectedBin);
//
// if (binsCount == this.selectedBin){
// paintColumnColor(_bins[binsCount]*unitY,
// paintX,
// paintXplus,
// paintZ,
// paintZplus,
// 255, 0, 0 );
// }
// else{
// System.out.println("*********************");
// System.out.println("bins["+binsCount+"]" +_bins[binsCount]*unitX);
// System.out.println("rangesX["+i+"]: "+_rangesX[i]);
// System.out.println("rangesZ["+j+"]: "+_rangesZ[j]);
paintColumnColor( _bins[binsCount]*unitY,
paintX,
paintXplus,
paintZ,
paintZplus,
cRed, cGreen, cBlue );
// }
binsCount++;
}
}
}
/**
* paints the coordinate system for the histogram2d
* @param minX
* @param maxX
* @param minZ
* @param maxZ
* @param minY
* @param maxY
* @param unitX
* @param unitZ
* @param unitY
*/
public void paintCoordinateSystemXYZ(double minX, double maxX, double minZ, double maxZ, double minY, double maxY, double unitX, double unitZ,
double unitY){
// System.out.println("im paintCoordingatesystemXYZ 1");
// Point3DVector pointVec = new Point3DVector();
Line3DVector lineVec = new Line3DVector();
//Triangle3DVector triaVec = new Triangle3DVector();
if (minX > 0.0){
minX = 0.0;
}
if (minY > 0.0){
minY = 0.0;
}
if (minZ > 0.0){
minZ = 0.0;
}
// System.out.println("im paintCoordingatesystemXYZ 2");
Point3D pNull = new Point3D(0, 0.0,0,0,0,0, id);
Point3D pXpositiv = new Point3D(maxX*unitX,0, 0, 0, 0, 0, id);
Point3D pXnegativ = new Point3D((maxX-minX)*unitX,0, 0, 0, 0, 0, id);
//y-axis for binheights
Point3D pYpositiv = new Point3D(0,maxY*unitY, 0, 0, 0, 0,id);
Point3D pYnegativ = new Point3D(0,minY*unitY, 0, 0, 0, 0,id);
Point3D pZpositiv = new Point3D(0,0, maxZ*unitZ, 0, 0, 0,id);
Point3D pZnegativ = new Point3D(0,0, (maxZ-minZ)*unitZ, 0, 0, 0,id);
Point3D pFront = new Point3D((maxX-minX)*unitX, 0, (maxZ-minZ)*unitZ, 0,0,0);
Point3D pZYUp = new Point3D(0, maxY*unitY, (maxZ-minZ)*unitZ, 0,0,0);
Point3D pXYUp = new Point3D((maxX-minX)*unitX, maxY*unitY, 0, 0,0,0);
Point3D pZYDown = new Point3D(0, minY*unitY, (maxZ-minZ)*unitZ, 0,0,0);
Point3D pXYDown = new Point3D((maxX-minX)*unitX, minY*unitY, 0, 0,0,0);
// System.out.println("im paintCoordingatesystemXYZ 3");
/*pointVec.append(pNull);
pointVec.append(pXpositiv);
pointVec.append(pXnegativ);
pointVec.append(pYpositiv);
pointVec.append(pYnegativ);
pointVec.append(pZpositiv);
pointVec.append(pZnegativ);
pointVec.append(pFront);
pointVec.append(pZYDown);
pointVec.append(pXYDown);
*/
Line3D Xpositiv = new Line3D(pNull, pXpositiv);
Line3D Xnegativ = new Line3D(pXpositiv, pXnegativ);
Line3D Ypositiv = new Line3D(pNull, pYpositiv);
Line3D Ynegativ = new Line3D(pNull, pYnegativ);
Line3D Zpositiv = new Line3D(pNull, pZpositiv);
Line3D Znegativ = new Line3D(pZpositiv, pZnegativ);
Line3D xToFront = new Line3D(pFront, pXnegativ);
Line3D zToFront = new Line3D(pFront, pZpositiv);
Line3D zmaxTomaxYZ = new Line3D(pZnegativ, pZYUp);
Line3D xmaxTomaxXY = new Line3D(pXnegativ, pXYUp);
Line3D upLineXY = new Line3D(pYpositiv, pZYUp);
Line3D upLineYZ = new Line3D(pYpositiv, pXYUp);
Line3D bottomLineZ = new Line3D(pZYDown, pYnegativ);
Line3D bottomLineX = new Line3D(pXYDown, pYnegativ);
Line3D XnegativeToYnegative = new Line3D(pXnegativ, pXYDown);
lineVec.append(bottomLineZ);
lineVec.append(bottomLineX);
lineVec.append(XnegativeToYnegative);
lineVec.append(Xpositiv);
lineVec.append(Xnegativ);
lineVec.append(Ypositiv);
lineVec.append(Ynegativ);
lineVec.append(Zpositiv);
lineVec.append(Znegativ);
lineVec.append(xToFront);
lineVec.append(zToFront);
lineVec.append(zmaxTomaxYZ);
lineVec.append(xmaxTomaxXY);
lineVec.append(upLineXY);
lineVec.append(upLineYZ);
//to paint the steps of the coordinatesystem XY columns and XZ columns
Vector rangeXIntervals = this.paintSteps(maxX, minX);
Iterator itx = rangeXIntervals.iterator();
Point3D[] stepsX = new Point3D[12];
Point3D[] stepsX_Ymax = new Point3D[12]; //above
Point3D[] stepsX_Ymin = new Point3D[12]; //above
Point3D[] stepsX_Zmax = new Point3D[12]; // bottom
Point3D[] stepsX_Zmin = new Point3D[12]; // bottom
Line3D[] lineXYColumn = new Line3D[12];
Line3D[] lineXYColumnMin = new Line3D[12];
Line3D[] lineXZColumn = new Line3D[12];
Line3D[] lineXZColumnMin = new Line3D[12];
int i = 0;
while (itx.hasNext() ){
double itxNext = ((Double)(itx.next())).doubleValue();
// System.out.println("itxNext: "+itxNext);
// System.out.println("i: "+i);
// System.out.println("itxNext*unitX: "+itxNext*unitX);
stepsX[i]= new Point3D((maxX-itxNext)*unitX, 0,0, 0,0,0);
stepsX_Ymax[i]= new Point3D((maxX-itxNext)*unitX, maxY*unitY,0, 0,0,0);
stepsX_Ymin[i]= new Point3D((maxX-itxNext)*unitX, minY*unitY,0, 0,0,0);
lineXYColumn[i] = new Line3D(stepsX[i], stepsX_Ymax[i]);
lineXYColumnMin[i] = new Line3D(stepsX[i], stepsX_Ymin[i]);
lineVec.append(lineXYColumn[i]);
lineVec.append(lineXYColumnMin[i]);
stepsX_Zmax[i] = new Point3D((maxX-itxNext)*unitX, 0,maxZ*unitZ, 0,0,0);
stepsX_Zmin[i] = new Point3D((maxX-itxNext)*unitX, 0,(maxZ-minZ)*unitZ, 0,0,0);
lineXZColumn[i] = new Line3D(stepsX_Zmax[i], stepsX[i]);
lineXZColumnMin[i] = new Line3D(stepsX_Zmin[i], stepsX[i]);
lineVec.append(lineXZColumn[i]);
lineVec.append(lineXZColumnMin[i]);
i++;
}
//to paint the steps of the coordinatesystem YZ columns and ZX rows
Vector rangeZIntervals = this.paintSteps(maxZ, minZ);
Iterator itz = rangeZIntervals.iterator();
Point3D[] stepsZ = new Point3D[12];
Point3D[] stepsZ_Ymax = new Point3D[12]; //above
Point3D[] stepsZ_Ymin = new Point3D[12]; //above
Point3D[] stepsZ_Xmax = new Point3D[12]; // bottom, row
Point3D[] stepsZ_Xmin = new Point3D[12]; // bottom, row
Line3D[] lineYZColumn = new Line3D[12];
Line3D[] lineYZColumnMin = new Line3D[12];
Line3D[] lineZXRow = new Line3D[12];
Line3D[] lineZXRowMin = new Line3D[12];
int j = 0;
while (itz.hasNext() ){
double itzNext = ((Double)(itz.next())).doubleValue();
// System.out.println("itzNext: "+itzNext);
stepsZ[j]= new Point3D(0, 0,(maxZ-itzNext)*unitZ, 0,0,0);
stepsZ_Ymax[j]= new Point3D(0, maxY*unitY,(maxZ-itzNext)*unitZ, 0,0,0);
stepsZ_Ymin[j]= new Point3D(0, minY*unitY,(maxZ-itzNext)*unitZ, 0,0,0);
lineYZColumn[j] = new Line3D(stepsZ[j], stepsZ_Ymax[j]);
lineYZColumnMin[j] = new Line3D(stepsZ[j], stepsZ_Ymin[j]);
lineVec.append(lineYZColumn[j]);
lineVec.append(lineYZColumnMin[j]);
stepsZ_Xmax[j] = new Point3D(maxX*unitX, 0,(maxZ-itzNext)*unitZ, 0,0,0);
stepsZ_Xmin[j] = new Point3D((maxX-minX)*unitX, 0,(maxZ-itzNext)*unitZ, 0,0,0);
lineZXRow[j] = new Line3D(stepsZ_Xmax[j], stepsZ[j]);
lineZXRowMin[j] = new Line3D(stepsZ_Xmin[j], stepsZ[j]);
lineVec.append(lineZXRow[j]);
lineVec.append(lineZXRowMin[j]);
j++;
}
//to paint the steps of the coordinatesystem YZ rows and YX rows
Vector rangeYIntervals = this.paintSteps(maxY, minY);
Iterator ity = rangeYIntervals.iterator();
Point3D[] stepsY = new Point3D[12];
Point3D[] stepsY_Xmax = new Point3D[12]; //above
Point3D[] stepsY_Xmin = new Point3D[12]; //above
Point3D[] stepsY_Zmax = new Point3D[12]; // bottom, row
Point3D[] stepsY_Zmin = new Point3D[12]; // bottom, row
Line3D[] lineYZRow = new Line3D[12];
Line3D[] lineYZRowMin = new Line3D[12];
Line3D[] lineYXRow = new Line3D[12];
Line3D[] lineYXRowMin = new Line3D[12];
int k = 0;
while (ity.hasNext() ){
double ityNext = ((Double)(ity.next())).doubleValue();
stepsY[k]= new Point3D(0, ityNext*unitY,0, 0,0,0);
stepsY_Xmax[k]= new Point3D(maxX*unitX, ityNext*unitY,0, 0,0,0);
stepsY_Xmin[k]= new Point3D((maxX-minX)*unitX, ityNext*unitY,0, 0,0,0);
lineYXRow[k] = new Line3D(stepsY[k], stepsY_Xmax[k]);
lineYXRowMin[k] = new Line3D(stepsY[k], stepsY_Xmin[k]);
lineVec.append(lineYXRow[k]);
lineVec.append(lineYXRowMin[k]);
stepsY_Zmax[k] = new Point3D(0, ityNext*unitY,maxZ*unitZ, 0,0,0);
stepsY_Zmin[k] = new Point3D(0, ityNext*unitY,(maxZ-minZ)*unitZ, 0,0,0);
lineYZRow[k] = new Line3D(stepsY_Zmax[k], stepsY[k]);
lineYZRowMin[k] = new Line3D(stepsY_Zmin[k], stepsY[k]);
lineVec.append(lineYZRow[k]);
lineVec.append(lineYZRowMin[k]);
k++;
}
// System.out.println("im paintCoordingatesystemXYZ end");
// this.add(pointVec); //to test
this.add(lineVec);
// this.add(triaVec);
}
/**
*
* @return vector of steps to be painted
*/
private Vector paintSteps(double max, double min){
Vector numbers = new Vector(20);
double distance = 0.0;
if (min < 0.0)
{
distance = max-min;
}
else
{
distance = max;
}
double step = this.getDisplayStep(distance, 5);
if(max<=0.0){
max = 0.0;
}
int countPositiv = (int)(max/step); //numbers of steps in positiv direction
if (min>=0.0){
min=0.0;
}
int countNegativ = (int)(Math.abs(min)/step);
for (int i = 0; i <= countPositiv; i++){
numbers.add(new Double(i*step));
}
for (int i = 1; i <= countNegativ; i++){
numbers.add(new Double(-i*step));
}
return numbers;
}
/**
*
* @param interval
* @param minSteps
* @return step distance to paint
*/
private static double getDisplayStep(double interval, double minSteps){
interval = Math.abs(interval);
if (interval == 0.0){
interval = 10;
}
double step;
double stepMin = interval/minSteps;
double magnitude = 1.0;
while(stepMin > 10){
stepMin/=10;
magnitude*=10;
}
//stepMin is between 0 and 100
while(stepMin < 1){
stepMin*=10;
magnitude/=10;
}
//stepMin between 1 and 10
if(stepMin < 2.0){
step = 2*magnitude;
}
else{
step = 5*magnitude;
}
return step;
}
}
public String toString() {
return "Histogram2d";
}
}