/** * */ package icy.roi; import icy.type.Position5DIterator; import icy.type.point.Point5D; import icy.type.rectangle.Rectangle5D; import java.util.NoSuchElementException; /** * ROI iterator.<br> * This class permit to use simple iterator to navigate each point of specified ROI in XYCZT * <i>([T[Z[C[Y[X]]]]])</i> dimension order.<br> * <b>If the ROI is modified during iteration the iterator becomes invalid and exception can * happen.</b> * * @author Stephane */ public class ROIIterator implements Position5DIterator { protected final ROI roi; protected final Rectangle5D.Integer bounds; protected final boolean inclusive; protected int c, z, t; protected boolean done; protected BooleanMask2DIterator maskIterator; /** * Create a new ROI iterator to iterate through each point of the specified ROI. * * @param roi * ROI defining the region to iterate. * @param region * A 5D region to limit the ROI region area to iterate for.<br/> * Keep it to <code>null</code> to iterate all over the ROI. * @param inclusive * If true then all partially contained (intersected) pixels in the ROI are included. */ public ROIIterator(ROI roi, Rectangle5D region, boolean inclusive) { super(); this.roi = roi; // get final bounds if (region != null) bounds = region.createIntersection(roi.getBounds5D()).toInteger(); else bounds = roi.getBounds5D().toInteger(); this.inclusive = inclusive; // fix infinite dimensions if (bounds.isInfiniteZ()) { bounds.z = -1; bounds.sizeZ = 1; } if (bounds.isInfiniteT()) { bounds.t = -1; bounds.sizeT = 1; } if (bounds.isInfiniteC()) { bounds.c = -1; bounds.sizeC = 1; } // start iterator reset(); } /** * Create a new ROI iterator to iterate through each point of the specified ROI. * * @param roi * ROI defining the region to iterate. * @param inclusive * If true then all partially contained (intersected) pixels in the ROI are included. */ public ROIIterator(ROI roi, boolean inclusive) { this(roi, null, inclusive); } public int getMinZ() { return bounds.z; } public int getMaxZ() { return (bounds.z + bounds.sizeZ) - 1; } public int getMinT() { return bounds.t; } public int getMaxT() { return (bounds.t + bounds.sizeT) - 1; } public int getMinC() { return bounds.c; } public int getMaxC() { return (bounds.c + bounds.sizeC) - 1; } @Override public void reset() { done = bounds.isEmpty(); if (!done) { z = getMinZ(); t = getMinT(); c = getMinC(); prepareXY(); nextXYIfNeeded(); } } /** * Prepare for XY iteration. */ protected void prepareXY() { maskIterator = new BooleanMask2DIterator(roi.getBooleanMask2D(z, t, c, inclusive)); } @Override public void next() { if (done) throw new NoSuchElementException(); maskIterator.next(); nextXYIfNeeded(); } /** * Advance one image position. */ protected void nextXYIfNeeded() { while (maskIterator.done() && !done) { if (++c > getMaxC()) { c = getMinC(); if (++z > getMaxZ()) { z = getMinZ(); if (++t > getMaxT()) { done = true; return; } } } prepareXY(); } } @Override public boolean done() { return done; } @Override public Point5D get() { if (done) throw new NoSuchElementException(); return new Point5D.Integer(maskIterator.getX(), maskIterator.getY(), z, t, c); } @Override public int getX() { if (done) throw new NoSuchElementException(); return maskIterator.getX(); } @Override public int getY() { if (done) throw new NoSuchElementException(); return maskIterator.getY(); } @Override public int getC() { if (done) throw new NoSuchElementException(); return c; } @Override public int getZ() { if (done) throw new NoSuchElementException(); return z; } @Override public int getT() { if (done) throw new NoSuchElementException(); return t; } }