package org.das2.graph;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.LinkedHashMap;
import java.util.Map;
import org.das2.datum.UnitsUtil;
import org.das2.qds.QDataSet;
import org.das2.qds.examples.Schemes;
import org.das2.qds.ops.Ops;
import static java.lang.Math.cos;
import static java.lang.Math.sin;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import org.das2.qds.DataSetUtil;
import org.das2.qds.SemanticOps;
/**
* Draw the region bounded by the dataset. If the dataset is a bounding box, the box is drawn. If the
* data is a rank 2 time series with bins (N by 2), then it is drawn. This supports the following
* types:
* - bounding box
*
- array of bounding box
*
- array of bins
*
* @author jbf
* @see org.das2.qds.examples.Schemes#isBoundingBox(org.das2.qds.QDataSet)
*/
public class BoundsRenderer extends Renderer {
private void expectDs() {
getParent().postException( this, new IllegalArgumentException("Expect rank 2 bins or rank 3 array of bins dataset") );
}
@Override
public boolean acceptsDataSet(QDataSet ds) {
if ( ds.rank()==1 || Schemes.isBoundingBox(ds) || Schemes.isArrayOfBoundingBox(ds) ) {
return true;
} else {
return false;
}
}
@Override
public boolean acceptContext(int x, int y) {
return context==null ? false : context.contains(x, y);
}
public Area selectionArea() {
if ( context==null ) {
return null;
} else {
return new Area(context);
}
}
@Override
public Icon getListIcon() {
Image i = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) i.getGraphics();
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
Shape pbox= new Rectangle2D.Double(0,0,15,15);
GeneralPath p= new GeneralPath();
p.append( pbox.getPathIterator(null), true );
p.closePath();
GraphUtil.fillWithTexture(g, p, fillColor, fillTexture );
g.draw(p);
return new ImageIcon(i);
}
@Override
public String getListLabel() {
return "" + ( getLegendLabel().length()> 0 ? getLegendLabel() +" " : "bounds" );
}
private GeneralPath context=null;
public static QDataSet doAutorange( QDataSet ds ) {
if ( ds.length()==0 ) {
return null;
}
if ( Schemes.isBoundingBox(ds) ) {
QDataSet xxx= Ops.slice0( ds,0 );
QDataSet yyy= Ops.slice0( ds,1 );
xxx= Ops.rescaleRangeLogLin( xxx, -0.1, 1.1 );
yyy= Ops.rescaleRangeLogLin( yyy, -0.1, 1.1 );
return Ops.join( xxx, yyy );
} else if ( Schemes.isArrayOfBoundingBox(ds) ) {
QDataSet xx=null;
QDataSet yy=null;
for ( int i=0; i controls= new LinkedHashMap();
controls.put( "fillColor", encodeColorControl(fillColor) );
controls.put( "color", encodeColorControl(color) );
if ( !fillTexture.isEmpty() ) controls.put( "fillTexture", fillTexture );
if ( polar ) controls.put( "polar", encodeBooleanControl( polar ) );
return Renderer.formatControl(controls);
}
@Override
public void setControl(String s) {
String oldControl= getControl();
super.setControl(s);
this.color= getColorControl( "color", color );
this.fillColor= getColorControl( "fillColor", fillColor );
this.fillTexture= getControl( "fillTexture", fillTexture );
this.polar= getBooleanControl( "polar", false );
if ( !oldControl.equals(s) ) {
updateCacheImage();
}
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
Color old = this.color;
this.color = color;
if ( !color.equals(old) ) {
updateCacheImage();
}
propertyChangeSupport.firePropertyChange(PROP_COLOR, old, color);
}
public Color getFillColor() {
return fillColor;
}
public void setFillColor( Color color ) {
Color old = this.fillColor;
this.fillColor = color;
if ( !color.equals(old) ) {
updateCacheImage();
}
propertyChangeSupport.firePropertyChange(PROP_COLOR, old, color );
}
private String fillTexture = "solid"; // solid, hash, none
public static final String PROP_FILLTEXTURE = "fillTexture";
public String getFillTexture() {
return fillTexture;
}
public void setFillTexture(String fillTexture) {
String old = this.fillTexture;
this.fillTexture = fillTexture;
if ( !old.equals(fillTexture) ) {
updateCacheImage();
}
propertyChangeSupport.firePropertyChange(PROP_FILLTEXTURE, old, fillTexture);
}
private boolean polar = false;
public static final String PROP_POLAR = "polar";
public boolean isPolar() {
return polar;
}
/**
* if true then transform render the data in polar coordinates
* @param polar
*/
public void setPolar(boolean polar) {
boolean old = this.polar;
this.polar = polar;
if ( old!=polar ) {
updateCacheImage();
}
propertyChangeSupport.firePropertyChange(PROP_POLAR, old, polar);
}
@Override
public void render(Graphics2D g1, DasAxis xAxis, DasAxis yAxis ) {
Graphics2D g= (Graphics2D)g1;
QDataSet d= this.getDataSet();
if ( d==null ) {
if ( getLastException()!=null ) {
renderException(g, xAxis, yAxis, lastException);
} else {
getParent().postMessage(this, "no data set", DasPlot.INFO, null, null);
}
return;
}
if ( d.length()==0 ) return;
if ( !( d.rank()==1 || d.rank()==2 || d.rank()==3 ) ) {
expectDs();
return;
}
QDataSet mins;
QDataSet maxs;
if ( Schemes.isBoundingBox(d) || Schemes.isBoundingBox(d.slice(0) )) {
if ( d.rank()==2 ) {
// make it a single-element rank 3
d= Ops.join( null, d );
}
GeneralPath pbox= new GeneralPath();
for ( int i=0; i