/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package org.das2.dataset; import java.awt.geom.Rectangle2D; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import org.das2.datum.Datum; import org.das2.datum.Units; import org.das2.qds.DataSetOps; import org.das2.qds.QDataSet; import org.das2.qds.SemanticOps; import org.das2.qds.WritableDataSet; import org.das2.qds.examples.Schemes; import org.das2.qds.ops.Ops; import org.das2.qds.util.DataSetBuilder; import org.das2.util.LoggerManager; /** * * @author jbf */ public class TriScatRebinner implements DataSetRebinner { private static final Logger logger = LoggerManager.getLogger("das2.data.rebinner"); ProGAL.geom2d.delaunay.DTWithBigPoints triangulation= null; WeakReference trids= null; /** * return the volume of the 3-point triangle in 2 dimensions. * See http://www.mathopenref.com/coordtrianglearea.html * @param a 2-d point corner * @param b 2-d point corner * @param c 2-d point corner * @return the volume */ private static double area( ProGAL.geom2d.Point a, ProGAL.geom2d.Point b, ProGAL.geom2d.Point c ) { return Math.abs( a.x() * ( b.y()- c.y() ) + b.x() * ( c.y() - a.y() ) + c.x() * ( a.y() - b.y() ) ) / 2; } /** * Point with placeholder for index. */ private static class VertexInt extends ProGAL.geom2d.delaunay.Vertex { int idx; VertexInt( double x, double y, int idx ) { super( x,y ); this.idx= idx; } @Override public String toString() { return String.format( "(%.1f,%.1f)", x(), y() ); } } private java.awt.geom.Rectangle2D getBounds( ProGAL.geom2d.delaunay.Triangle t ) { Rectangle2D.Double r= new Rectangle2D.Double( t.getCorner(0).x(), t.getCorner(0).y(), 0, 0 ); r.add( new java.awt.geom.Point2D.Double( t.getCorner(1).x(), t.getCorner(1).y() )); r.add( new java.awt.geom.Point2D.Double( t.getCorner(2).x(), t.getCorner(2).y() )); return r; } private boolean nearestNeighbor = false; public static final String PROP_NEARESTNEIGHBOR = "nearestNeighbor"; public boolean isNearestNeighbor() { return nearestNeighbor; } public void setNearestNeighbor(boolean nearestNeighbor) { this.nearestNeighbor = nearestNeighbor; } @Override public QDataSet rebin(QDataSet ds, RebinDescriptor ddX, RebinDescriptor ddY, RebinDescriptor ddZ ) { // throws IllegalArgumentException, DasException { LoggerManager.resetTimer("triscat rebin"); WritableDataSet result = Ops.zeros(ddX.numberOfBins(), ddY.numberOfBins()); ddX.setOutOfBoundsAction(RebinDescriptor.MINUSONE); ddY.setOutOfBoundsAction(RebinDescriptor.MINUSONE); QDataSet zz; if ( Schemes.isSimpleSpectrogram(ds) ) { zz= Ops.flatten(ds); } else { zz= ds; } QDataSet xx; QDataSet yy; if (Schemes.isBundleDataSet(zz)) { logger.fine("is bundle"); xx = DataSetOps.slice1(zz, 0); yy = DataSetOps.slice1(zz, 1); zz = DataSetOps.slice1(zz, zz.length(0) - 1); } else { if (!(zz.property(QDataSet.DEPEND_0) == null)) { xx = (QDataSet) zz.property(QDataSet.DEPEND_0); } else { xx = Ops.findgen(zz.length()); } if (!(zz.property(QDataSet.DEPEND_1) == null)) { yy = (QDataSet) zz.property(QDataSet.DEPEND_1); } else { if (Schemes.isLegacyXYZScatter(zz)) { yy = zz; zz = (QDataSet) yy.property(QDataSet.PLANE_0); } else { yy = Ops.findgen(zz.length()); } } } LoggerManager.markTime("got X Y Z datasets"); // scale and fuzz the data so there are no collinear points QDataSet extentX= Ops.extent(xx); QDataSet extentY= Ops.extent(yy); double[] dX= new double[] { extentX.value(0), extentX.value(1)-extentX.value(0) }; double[] dY= new double[] { extentY.value(0), extentY.value(1)-extentY.value(0) }; ProGAL.geom2d.delaunay.DTWithBigPoints rt; QDataSet ds1= trids==null ? null : trids.get(); if ( ds1==null || ds1!=ds ) { List points= new ArrayList(xx.length()); double fuzz= 0.0001; for ( int i=0; i=0; iy+=dir ) { // Boustrophedon back and forth ProGAL.geom2d.Point thePoint= new ProGAL.geom2d.Point( (ddX.binCenter(ix,xunits)-dX[0])/dX[1], (ddY.binCenter(iy,yunits)-dY[0])/dY[1] ); ProGAL.geom2d.delaunay.Triangle t1= rt.walk( thePoint, null, t ); if ( t1!=t ) { Rectangle2D r= getBounds(t1); triUsable= r.getWidth() < xlimit && r.getHeight()w[1] ) { if ( w[0]>w[2] ) { d= zz.value( abci[0].idx ); } else { d= zz.value( abci[2].idx ); } } else { if ( w[1]>w[2] ) { d= zz.value( abci[1].idx ); } else { d= zz.value( abci[2].idx ); } } result.putValue( ix, iy, d ); } else { try { d= zz.value( abci[0].idx ) * w[0] + zz.value( abci[1].idx ) * w[1] + zz.value( abci[2].idx ) * w[2]; result.putValue( ix, iy, d ); } catch ( NullPointerException ex ) { System.err.println("here151"); d= zz.value( abci[0].idx ) * w[0] + zz.value( abci[1].idx ) * w[1] + zz.value( abci[2].idx ) * w[2]; result.putValue( ix, iy, d ); } } } } dir= -dir; } LoggerManager.markTime("done interp all pixels"); org.das2.qds.DataSetUtil.copyDimensionProperties( zz, result ); RebinDescriptor.putDepDataSet( ds, result, ddX, ddY ); if ( !hasFill ) { result.putProperty( QDataSet.FILL_VALUE, null ); } result.putProperty( "TRIANGULATION", rt ); return result; } }