//*********************************************************************************
// class jephem.tools.Curve
// Software released under the General Public License (version 2 or later), available at
// http://www.gnu.org/copyleft/gpl.html
//*********************************************************************************
package jephem.tools;
import jephem.astro.spacetime.SpaceConstants;
import jephem.GlobalVar;
import jephem.util.Debug;
import tig.GeneralConstants;
import tig.maths.Maths;
import tig.maths.Vector2;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.geom.*;
import java.io.*;
/******************************************************************************
Visual representation of curve plotting.
Used with {@link jephem.gui.CurveViewer}, which contains the controls surrounding a <CODE>Curve</CODE>.
@author Thierry Graff
@history may 10 2002 : creation.
@todo
*********************************************************************************/
public class Curve extends JPanel implements SpaceConstants, GeneralConstants{
//=================================================================================
// INSTANCE VARIABLES
//=================================================================================
//***************** Data characteristics ******************
/** The data to display. */
private double[][] _data;
/** Number of values to be represented for each curve. */
private int _nbValues;
/** Number of curves represented. */
private int _nbCurves;
/** min and max values in data coordinates. */
private double _xMin, _xMax, _yMin, _yMax;
//***************** Axis characteristics ******************
/** Point were the axis intersect, in pixel coordinates.
Define the vert. and hor. positions of the axis. */
private Vector2 _axisCenter;
/** Intervals for which the values are displayed on the axis. */
private double _intervalX, _intervalY;
/** Space taken by the axis for the display (in pixels). */
private int _axisSpaceX, _axisSpaceY;
//***************** Display area characteristics ******************
/** Supplementary gaps between the axis and the border of the display area. */
int _xGap, _yGap;
/** height and width of the display area */
int _h, _w;
//=================================================================================
// PRIVATE CONSTANTS
//=================================================================================
private final static BasicStroke STROKE = new BasicStroke(1.0f);
private final static BasicStroke STROKE2 = new BasicStroke(2.0f);
//=================================================================================
// CONSTRUCTORS
//=================================================================================
/** Unique constructor. The base frame is set to equatorial frame. */
public Curve(){
super();
try {
this.setLayout(new BorderLayout());
this.setBackground(Color.WHITE);
calcHW();
_xGap = 10;// to do : consider the case _w < _xGap
_yGap = 10;// to do : consider the case _h < _yGap
_axisSpaceX = 30;
_axisSpaceY = 30;
}
catch(Exception e) {
Debug.traceError(e);
}
}// end constructor
//=================================================================================
// PUBLIC METHODS
//=================================================================================
//*************** get / set data ***************
/** Returns the data displayed by this curve.
<BR>If the returned value is called 'data' :
<BR><CODE>data[0]</CODE> contains the values of the X axis ;
<BR><CODE>data[1]</CODE> contains the values of the first quantity on the Y axis ;
<BR><CODE>data[2]</CODE> contains the values of the second quantity on the Y axis ;
<BR>etc...
*/
public double[][] getData(){ return _data; }
/** Sets the data displayed by this curve.
<BR>Meaning of parameter 'data' :
<BR><CODE>data[0]</CODE> contains the values of the X axis ;
<BR><CODE>data[1]</CODE> contains the values of the first quantity on the Y axis ;
<BR><CODE>data[2]</CODE> contains the values of the second quantity on the Y axis ;
<BR>etc...
<BR>WARNING : the arrays <CODE>data[0]</CODE>, <CODE>data[1]</CODE> etc... must have the same length.
*/
public void setData(double[][] data){
// check length
if(data.length < 2)
throw new IllegalArgumentException("Incorrect len of parameter ' data' - Must have at least two lines");
int len = data[0].length;
for (int i = 0; i < data.length; i++) {
if(data[i].length != len)
throw new IllegalArgumentException("Incorrect len of parameter ' data' - see jephem.tools.Curve.setData() documentation");
}
_data = data;
_nbValues = len; // all data[i] have the same length.
_nbCurves = _data.length - 1;
//System.out.println("_nbValues = " + _nbValues);
//System.out.println("_nbCurves = " + _nbCurves);
calcMinAndMax();
}// end setData
//*****************************************************************************
//****************************** paintComponent *******************************
//*****************************************************************************
/** Paints the curve on its display area. */
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
calcHW();
_axisCenter = new Vector2(_xGap + (double)_axisSpaceX/2, _h - (_yGap + (double)_axisSpaceY/2));
g2.setStroke(STROKE);
drawAxis(g2);
// Draw the curves
g2.setStroke(STROKE2);
g2.setPaint(Color.BLACK);
Vector2 v0D, v1D, v0P, v1P; // P and D for Pixel and Data coordinates
for(int i = 1; i <= _nbCurves; i++){
v0D = new Vector2(_data[0][0], _data[i][0]); // first point to draw
for(int j = 0; j < _nbValues - 1; j++){
v1D = new Vector2(_data[0][j+1], _data[i][j+1]); // second point to draw
// change to pixel coords
v0P = dataToPixel(v0D);
v1P = dataToPixel(v1D);
g2.draw(new Line2D.Double((int)v0P.x0, (int)v0P.x1, (int)v1P.x0, (int)v1P.x1));
// v0D takes the value of v1D
v0D = v1D;
}// end for j
}// end for i
}// end paintComponent
//=================================================================================
// PRIVATE METHODS
//=================================================================================
//********************** pixelToData **********************
/** Converts pixel coordinates to data coordinates. */
private Vector2 pixelToData(Vector2 vP){
// Formulae found from dataToPixel()
double a, b;
// conversion for x
a = (_xMax - _xMin)/((double)_w - 2*(double)_xGap);
b = -((double)_xGap*(_xMax + _xMin) - (double)_w*_xMin)/((double)_w - 2*(double)_xGap);
double xD = a*vP.x0 + b;
// conversion for y
a = (_yMin - _yMax)/((double)_h - 2*(double)_yGap);
b = -((double)_yGap*(_yMax + _yMin) - (double)_h*_yMax)/((double)_h - 2*(double)_yGap);
double yD = a*vP.x1 + b;
return new Vector2(xD, yD);
}// end pixelToData
//********************** dataToPixel **********************
/** Converts data coordinates to pixel coordinates. */
private Vector2 dataToPixel(Vector2 vD){
double a, b;
// conversion for x
a = ((double)_w - 2*(double)_xGap)/(_xMax - _xMin);
b = ((double)_xGap*(_xMax + _xMin) - (double)_w*_xMin)/(_xMax - _xMin);
double xP = a*vD.x0 + b;
// conversion for y
a = ((double)_h - 2*(double)_yGap)/(_yMin - _yMax);
b = ((double)_yGap*(_yMax + _yMin) - (double)_h*_yMax)/(_yMin - _yMax);
double yP = a*vD.x1 + b;
return new Vector2(xP, yP);
}// end dataToPixel
//********************** calcMinAndMax **********************
/** Computes from _data the min and max values to display on the x and y axis.
@post _xMin, _xMax, _yMin, _yMax are computed.
*/
private void calcMinAndMax(){
_xMin = Maths.min(_data[0]);
_xMax = Maths.max(_data[0]);
_yMin = Maths.min(_data[1]);
_yMax = Maths.max(_data[1]);
double yMin, yMax;
for (int i = 2; i <= _nbCurves; i++) {
yMin = Maths.min(_data[i]);
yMax = Maths.max(_data[i]);
if(yMin < _yMin) _yMin = yMin;
if(yMax > _yMax) _yMax = yMax
;
}
//System.out.println("_xMin = " + _xMin);
//System.out.println("_xMax = " + _xMax);
//System.out.println("_yMin = " + _yMin);
//System.out.println("_yMax = " + _yMax);
}// end calcMinAndMax
//*************** calcRHW ***************
/** Computes the height and width of the panel. */
private void calcHW(){
// height, width of the panel
_w = this.getSize().width;
_h = this.getSize().height;
}// end calcHW
//*************** drawAxis ***************
/** Computes the height and width of the panel. */
private void drawAxis(Graphics2D g2){
int posX = (int)_axisCenter.x0;
int posY = (int)_axisCenter.x1;
//System.out.println("posX = " + posX + " posY = " + posY);
g2.draw(new Line2D.Double(_xGap, posY, _w - _xGap, posY)); // X axis
g2.draw(new Line2D.Double(posX, _h - _yGap, posX, _yGap)); // Y axis
}// end drawAxis
}// end class SkyMap