/*
* $Id: ContourLine.java,v 1.16 2002/06/24 23:19:21 dwd Exp $
*
* This software is provided by NOAA for full, free and open release. It is
* understood by the recipient/user that NOAA assumes no liability for any
* errors contained in the code. Although this software is released without
* conditions or restrictions in its use, it is expected that appropriate
* credit be given to its author and to the National Oceanic and Atmospheric
* Administration should the software be included by the recipient as an
* element in other product development.
*/
package sgtplot.contour;
import java.util.Vector;
import java.util.Enumeration;
import java.awt.Graphics;
import java.awt.Color;
import org.freehep.graphics2d.VectorGraphics;
import sgtplot.CartesianGraph;
import sgtplot.ContourLineAttribute;
import sgtplot.DefaultContourLineAttribute;
import sgtplot.JPane;
import sgtplot.LayerNotFoundException;
import sgtplot.LineAttribute;
import sgtplot.SGLabel;
import sgtplot.StrokeDrawer;
import sgtplot.util.GeoDate;
import sgtplot.util.Point2D;
/**
* ContourLine contains a single closed or open contour
* and a list of its labels.
* The level, closedness, and path are properties.
* The path is stored as a Vector of Point2D
* user coordinate values. ContourLine objects are
* created by Contour and drawn by
* GridCartesianRenderer. Time coordinates are stored in
* the Point2D objects releative to a reference time.
*
* @author D. W. Denbo
* @version $Revision: 1.16 $, $Date: 2002/06/24 23:19:21 $
* @since 2.0
* @see Contour
* @see ContourLineAttribute
* @see DefaultContourLineAttribute
* @see sgtplot.GridCartesianRenderer
*/
public class ContourLine extends Vector {
private StrokeDrawer stroke_ = null;
private boolean closed_ = false;
private double level_;
private GeoDate timeRef_ = null;
private boolean xTime_ = false;
private boolean yTime_ = false;
private int kmax_;
/**
* @label attr
*/
private ContourLineAttribute attr_ = null;
private DefaultContourLineAttribute defaultAttr_ = null;
private Vector conLabels_;
/**
* @supplierCardinality *
* @link aggregationByValue
*/
private ContourLabel lnkContourLabel;
private CartesianGraph cg_;
/**
* Default constructor.
*/
public ContourLine() {
super();
conLabels_ = new Vector();
stroke_ = JPane.getStrokeDrawer();
}
/**
* Constructor setting initial size and extend values of coordinate
* Vector.
*/
public ContourLine(int size, int extend) {
super(size, extend);
conLabels_ = new Vector();
stroke_ = JPane.getStrokeDrawer();
}
/**
* Constructor setting initial size of coordinate Vector.
*/
public ContourLine(int size) {
super(size);
conLabels_ = new Vector();
stroke_ = JPane.getStrokeDrawer();
}
/**
* Set the parent CartesianGraph. Used internally by
* sgtplot.
*/
public void setCartesianGraph(CartesianGraph cg) {
cg_ = cg;
}
/**
* Set the attributes for the contour line.
*/
public void setAttributes(DefaultContourLineAttribute def, ContourLineAttribute attr) {
defaultAttr_ = def;
attr_ = attr;
}
/**
* Set the ContourLineAttribute
*/
public void setContourLineAttribute(ContourLineAttribute attr) {
attr_ = attr;
}
/**
* Get the ContourLineAttribute
*/
public ContourLineAttribute getContourLineAttribute() {
return attr_;
}
/**
* Set the DefaultContourLineAttribute
*/
public void setDefaultContourLineAttribute(DefaultContourLineAttribute def) {
defaultAttr_ = def;
}
/**
* Get the DefaultContourLineAttribute
*/
public DefaultContourLineAttribute getDefaultContourLineAttribute() {
return defaultAttr_;
}
void setClosed(boolean closed){
closed_ = closed;
}
/**
* Is the contour line closed?
*/
public boolean isClosed() {
return closed_;
}
/**
* The level value of the contour line.
*/
public double getLevel(){
return level_;
}
void setLevel(double level){
level_ = level;
}
void addPoint(double x, double y) {
addElement(new Point2D.Double(x, y));
}
void addPoint(Point2D.Double point) {
addElement(point);
}
void setKmax(int kmax) {
kmax_ = kmax;
}
/**
* Get the number of points in the contour line.
*/
public int getKmax() {
return kmax_;
}
void setTime(GeoDate tref, boolean xtime, boolean ytime) {
timeRef_ = tref;
xTime_ = xtime;
yTime_ = ytime;
}
void setReferenceTime(GeoDate tref) {
timeRef_ = tref;
}
/**
* Get reference time for the time point of the Point2D object.
*/
public GeoDate getReferenceTime() {
return timeRef_;
}
void setXTime(boolean time) {
xTime_ = time;
}
/**
* Is the x coordinate time?
*/
public boolean isXTime() {
return xTime_;
}
void setYTime(boolean time) {
yTime_ = time;
}
/**
* Is the y coordinate time?
*/
public boolean isYTime() {
return yTime_;
}
void reverseElements(int k) {
/* k is reversal length */
Point2D.Double point;
int kkr;
int kh = 1 + k/2;
for(int kk=1; kk < kh; kk++) {
kkr = k+1-kk;
point = (Point2D.Double)elementAt(kk);
setElementAt(elementAt(kkr), kk);
setElementAt(point, kkr);
}
}
/**
* Add a label to the contour line.
*/
public void addLabel(int point, SGLabel lab, double hgt, double wid) {
ContourLabel clab = new ContourLabel(point, lab, hgt, wid);
conLabels_.addElement(clab);
}
/**
* Remove all labels.
*/
public void removeAllLabels() {
conLabels_.removeAllElements();
}
/**
* Used internally by sgtplot.
*/
public void draw(VectorGraphics g) {
int k, kk, loc, kp1;
double[] x = new double[kmax_+1];
double[] y = new double[kmax_+1];
ContourLabel clab;
double width, hhgt;
double dxx, dyy, space;
double xa, xb, ya, yb, aa, bb, cc, zxy;
double xendl, yendl, angle;
double xlab, ylab;
SGLabel label;
GeoDate time;
defaultAttr_.setContourLineAttribute(attr_);
Color lineColor = defaultAttr_.getColor();
//
// convert ContourLine to physical units
//
x = getXArrayP();
y = getYArrayP();
//
// loop through labels
//
k=1;
Enumeration cenum = conLabels_.elements();
while(cenum.hasMoreElements()) {
clab = (ContourLabel)cenum.nextElement();
loc = clab.getIndex();
width = clab.getWidth();
hhgt = clab.getHeight()*0.5;
label = clab.getLabel();
//
g.setColor(lineColor);
drawLine(g, x, y, k, loc);
//
k = loc;
kp1 = k + 1;
for(kk=kp1; kk <= kmax_; kk++) {
dxx = x[kk] - x[k];
dyy = y[kk] - y[k];
space = Math.sqrt(dxx*dxx+dyy*dyy);
if(space >= width) break;
}
xa = x[kk-1] - x[k];
xb = x[kk] - x[kk-1];
ya = y[kk-1] - y[k];
yb = y[kk] - y[kk-1];
aa = xb*xb + yb*yb;
bb = xa*xb + ya*yb;
cc = xa*xa + ya*ya - width*width;
zxy = (-bb + Math.sqrt(bb*bb - aa*cc))/aa;
dxx = xa + xb*zxy;
dyy = ya + yb*zxy;
xendl = x[k] + dxx;
yendl = y[k] + dyy;
//
// compute label angle
//
angle = 90.0;
if(dyy < 0.0) angle = -90.0;
if(dxx != 0.0) {
angle = Math.atan(dyy/dxx)*180.0/Math.PI;
}
//
// compute label position
//
if(dxx >= 0) {
xlab = x[k] + hhgt*(0.5*dxx + dyy)/width;
ylab = y[k] + hhgt*(0.5*dyy - dxx)/width;
} else {
xlab = xendl - hhgt*(0.5*dxx + dyy)/width;
ylab = yendl - hhgt*(0.5*dyy - dxx)/width;
}
label.setAngle(angle);
label.setLocationP(new Point2D.Double(xlab, ylab));
try {
label.draw(g);
} catch (LayerNotFoundException e) {
System.out.println(e);
}
g.setColor(lineColor);
drawLineSegment(g, xendl, yendl, x[kk], y[kk]);
k=kk;
}
if(k < kmax_) {
g.setColor(lineColor);
drawLine(g, x, y, k, kmax_);
}
}
private void drawLine(VectorGraphics g, double[] x, double[] y,
int kstart, int kend) {
int size = kend-kstart+1;
int[] xp = new int[size];
int[] yp = new int[size];
int i, k;
for(i=0, k=kstart; k <= kend; k++, i++) {
xp[i] = cg_.getLayer().getXPtoD(x[k]);
yp[i] = cg_.getLayer().getYPtoD(y[k]);
}
switch(defaultAttr_.getStyle()) {
case LineAttribute.HIGHLIGHT:
stroke_.drawHighlight(g, xp, yp, size, (LineAttribute)defaultAttr_);
break;
case LineAttribute.HEAVY:
stroke_.drawHeavy(g, xp, yp, size, (LineAttribute)defaultAttr_);
break;
case LineAttribute.DASHED:
stroke_.drawDashed(g, xp, yp, size, (LineAttribute)defaultAttr_);
break;
case LineAttribute.STROKE:
stroke_.drawStroke(g, xp, yp, size, (LineAttribute)defaultAttr_);
break;
default:
case LineAttribute.MARK:
case LineAttribute.MARK_LINE:
case LineAttribute.SOLID:
g.drawPolyline(xp, yp, size);
}
}
private void drawLineSegment(VectorGraphics g, double x0, double y0,
double x1, double y1) {
int[] xp, yp;
int size = 2;
xp = new int[2];
yp = new int[2];
xp[0] = cg_.getLayer().getXPtoD(x0);
yp[0] = cg_.getLayer().getYPtoD(y0);
xp[1] = cg_.getLayer().getXPtoD(x1);
yp[1] = cg_.getLayer().getYPtoD(y1);
switch(defaultAttr_.getStyle()) {
case LineAttribute.HIGHLIGHT:
stroke_.drawHighlight(g, xp, yp, size, (LineAttribute)defaultAttr_);
break;
case LineAttribute.HEAVY:
stroke_.drawHeavy(g, xp, yp, size, (LineAttribute)defaultAttr_);
break;
case LineAttribute.DASHED:
stroke_.drawDashed(g, xp, yp, size, (LineAttribute)defaultAttr_);
break;
case LineAttribute.STROKE:
stroke_.drawStroke(g, xp, yp, size, (LineAttribute)defaultAttr_);
break;
default:
case LineAttribute.MARK:
case LineAttribute.MARK_LINE:
case LineAttribute.SOLID:
g.drawPolyline(xp, yp, size);
}
}
/**
* Get x physical coordinates of the contour line.
*/
public double[] getXArrayP() {
double[] xp = null;
Point2D.Double pt;
GeoDate time;
if(cg_ != null) {
xp = new double[kmax_+1];
for(int k=0; k <= kmax_; k++) {
pt = (Point2D.Double)elementAt(k);
if(isXTime()) {
time = (new GeoDate(timeRef_)).increment(pt.x, GeoDate.DAYS);
xp[k] = cg_.getXUtoP(time);
} else {
xp[k] = cg_.getXUtoP(pt.x);
}
}
}
return xp;
}
/**
* Get y physical coordinates of the contour line.
*/
public double[] getYArrayP() {
double[] yp = null;
Point2D.Double pt;
GeoDate time;
if(cg_ != null) {
yp = new double[kmax_+1];
for(int k=0; k <= kmax_; k++) {
pt = (Point2D.Double)elementAt(k);
if(isYTime()) {
time = (new GeoDate(timeRef_)).increment(pt.x, GeoDate.DAYS);
yp[k] = cg_.getYUtoP(time);
} else {
yp[k] = cg_.getYUtoP(pt.y);
}
}
}
return yp;
}
}
Ads help maintain this website.