package jas.hist.util; import jas.hist.Rebinnable2DHistogramData; import jas.hist.ScatterEnumeration; import jas.hist.ScatterPlotSource; import javax.swing.event.EventListenerList; /** * Takes as its source a Rebinnable2DHistogramData which also * implements HasScatterPlotData and in addition to relaying the source * data to the destination, also implements HasSlices and SliceAdapter */ public class ScatterSliceAdapter extends TwoDSliceAdapter { private EventListenerList listenerList = new EventListenerList(); public ScatterSliceAdapter(Rebinnable2DHistogramData source) { super(source); } public ScatterSliceAdapter(ScatterPlotSource source) { super(new ScatterTwoDAdapter(source)); } public int addSlice(double x, double y, double width, double height, double phi) { if (scatter != null && scatter.hasScatterPlotData()) { int n = slices.size(); String title = (width==Double.POSITIVE_INFINITY?"Projection ":"Slice ")+n; slices.addElement(new Slice(title,x,y,width,height,phi)); fireSliceAdded(n); return n; } else return super.addSlice(x,y,width,height,phi); } private class Slice extends AbstractSlice { private double m_min, m_max; private boolean minMaxValid = false; Slice(String title, double x, double y, double width, double height, double phi) { super(title, (width == Double.POSITIVE_INFINITY)); this.parm = new DefaultSliceParameters(x,y,width,height,phi) { protected void changed() { sendUpdate(); } }; } public void sendUpdate() { minMaxValid = false; super.sendUpdate(); } public double[][] rebin(int bins, double min, double max, boolean wantErrors, boolean hurry) { double[] hist = new double[bins]; ScatterEnumeration e = scatter.startEnumeration(); double sinPhi = Math.sin(parm.phi); double cosPhi = Math.cos(parm.phi); double p0 = -parm.x*sinPhi + parm.y*cosPhi; double q0 = parm.x*cosPhi + parm.y*sinPhi; double[] point = new double[2]; while (e.getNextPoint(point)) { double q = point[0]*cosPhi + point[1]*sinPhi; if (!projection) { if (Math.abs(q-q0) > parm.width) continue; double p = - point[0]*sinPhi + point[1]*cosPhi; if (Math.abs(p-p0) > parm.height) continue; } if (q<min) continue; int bin = (int) ((q-min)*bins/(max-min)); if (bin >= bins) continue; hist[bin]++; } double[][] result = { hist }; return result; } private void calcMinMax() { minMaxValid = true; if (projection) { ScatterEnumeration e = scatter.startEnumeration(); double sinPhi = Math.sin(parm.phi); double cosPhi = Math.cos(parm.phi); double[] point = new double[2]; double min = 0; double max = 0; for (boolean first=true; e.getNextPoint(point); first=false) { double q = point[0]*cosPhi + point[1]*sinPhi; if (first) min = max = q; else { min = Math.min(min,q); max = Math.max(max,q); } } m_min = min; m_max = max; } else { double sinPhi = Math.sin(parm.phi); double cosPhi = Math.cos(parm.phi); double q0 = parm.x*cosPhi + parm.y*sinPhi; m_min = q0-parm.width; m_max = q0+parm.width; } } public double getMin() { if (!minMaxValid) calcMinMax(); return m_min; } public double getMax() { if (!minMaxValid) calcMinMax(); return m_max; } public int getBins() { return 40; } public boolean isRebinnable() { return true; } } }