/*
* Copyright (C) 2014 - Martin Berger
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/
package edu.stanford.rsl.conrad.data.generic.iterators;
import edu.stanford.rsl.conrad.data.PointwiseIterator;
import edu.stanford.rsl.conrad.data.generic.GenericGrid;
import edu.stanford.rsl.conrad.data.generic.complex.ComplexGrid3D;
import edu.stanford.rsl.conrad.data.generic.datatypes.Complex;
import edu.stanford.rsl.conrad.data.generic.datatypes.Gridable;
public class GenericFloatIterator<T extends Gridable<T>> extends PointwiseIterator{
protected GenericGrid<T> m_grid;
/**
* The condition for out of bound values
* 0 = clamp to zero
* 1 = clamp to constant
* 2 = clamp to edge value
* 3 = symmetrically extend value
* 4 = extend periodically
*/
protected int boundaryCondition;
/**
* The boundary size for each dimension.
* Half of the boundary size is extended in each direction.
* If N is the given size and N is odd, the boundary on the right side is extended by N/2 + 1,
* whereas the boundary on the left side is extended by N/2.
*/
protected int[] boundarySize;
/**
* The value to set the boundary if using a clamp to constant boundary condition
*/
protected T clampValue;
/**
* The iterators direction
*/
protected int[] direction;
/**
* The current iterator position
*/
protected int[] position;
protected int dim;
public GenericFloatIterator(GenericGrid<T> g, T clampValue){
this(g, 0, new int[g.getSize().length], clampValue, new int[g.getSize().length]);
}
public GenericFloatIterator(GenericGrid<T> g, int boundCond, int[] boundSize, T clampValue, int[] pos, int []dir) {
// set the grid
this.m_grid = g;
// initialize the boundaries
boundaryCondition = boundCond;
boundarySize = boundSize;
this.clampValue = clampValue;
// set initial direction
direction = dir;
// set initial position
position = pos;
// the dimension
dim = g.getSize().length;
}
public GenericFloatIterator(GenericGrid<T> g, int boundCond, int[] boundSize, T clampValue, int[] pos) {
// set the grid
this.m_grid = g;
// initialize the boundaries
boundaryCondition = boundCond;
boundarySize = boundSize;
this.clampValue = clampValue;
// set initial direction
direction = new int[g.getSpacing().length];
direction[0]=1;
// set initial position
position = pos;
// the dimension
dim = g.getSize().length;
}
public boolean hasNext(){
boolean val = true;
for (int i=0; i < dim; ++i){
int tmp = position[i];
if (tmp < 0 - boundarySize[i]/2 || tmp >= m_grid.getSize()[i] + boundarySize[i]/2 + boundarySize[i]%2)
val = false;
}
return val;
}
private void move(){
for (int i=0; i < dim; ++i)
position[i]+=direction[i];
}
public T getNext(){
int[] currentPosition = null;
T val = null;
for (int i=0; i < dim; ++i){
boolean bleft=position[i] < 0;
boolean bright=position[i] >= m_grid.getSize()[i];
// check if we have a boundary case
if (bleft || bright) {
switch (boundaryCondition) {
case 0:
val = clampValue.getNewInstance();
break;
case 1:
val = clampValue;
break;
case 2:
currentPosition = (currentPosition==null) ? position.clone() : currentPosition;
currentPosition[i] = (bleft) ? 0 : m_grid.getSize()[i]-1;
break;
case 3:
currentPosition = (currentPosition==null) ? position.clone() : currentPosition;
// TODO not save if grid dimension is smaller than the boundary
currentPosition[i] = (bleft) ? Math.abs(position[i]) -1 : m_grid.getSize()[i] - (position[i] % m_grid.getSize()[i]) -1;
break;
case 4:
currentPosition = (currentPosition==null) ? position.clone() : currentPosition;
currentPosition[i] = (bleft) ? m_grid.getSize()[i] + ((position[i]+1) % m_grid.getSize()[i]) -1 : (position[i] % m_grid.getSize()[i]);
break;
default:
break;
}
}
}
T out = (val != null) ? val : ((currentPosition!=null) ? m_grid.getValue(currentPosition) : m_grid.getValue(position));
this.move();
return out;
}
public int[] getPosition(){
return position;
}
public void setPosition(int... pos){
position = pos;
}
public void setDirection(int... dir){
direction = dir;
}
public int[] getDirection(){
return direction.clone();
}
public static void main(String[] args) {
GenericGrid<Complex> g = new ComplexGrid3D(8,8,12);
for (int i=0; i < 8; i++){
for (int j=0; j<8; j++)
for (int k=0; k<12; k++)
((ComplexGrid3D)g).setAtIndex(i, j, k, i, j*k);
}
GenericFloatIterator<?> it = new GenericFloatIterator<Complex>(g,4,new int[]{0,0,0},new Complex(),new int[]{0,7,0},new int[]{0,0,1});
while (it.hasNext())
{
System.out.print(it.getPosition()[0]+ "/" + it.getPosition()[1] + ": " + it.getNext() + "\n");
}
}
}