001/** 002 * 003 */ 004package icy.roi; 005 006import icy.type.Position5DIterator; 007import icy.type.point.Point5D; 008import icy.type.rectangle.Rectangle5D; 009 010import java.util.NoSuchElementException; 011 012/** 013 * ROI iterator.<br> 014 * This class permit to use simple iterator to navigate each point of specified ROI in XYCZT 015 * <i>([T[Z[C[Y[X]]]]])</i> dimension order.<br> 016 * <b>If the ROI is modified during iteration the iterator becomes invalid and exception can 017 * happen.</b> 018 * 019 * @author Stephane 020 */ 021public class ROIIterator implements Position5DIterator 022{ 023 protected final ROI roi; 024 protected final Rectangle5D.Integer bounds; 025 protected final boolean inclusive; 026 protected int c, z, t; 027 protected boolean done; 028 protected BooleanMask2DIterator maskIterator; 029 030 /** 031 * Create a new ROI iterator to iterate through each point of the specified ROI. 032 * 033 * @param roi 034 * ROI defining the region to iterate. 035 * @param region 036 * A 5D region to limit the ROI region area to iterate for.<br/> 037 * Keep it to <code>null</code> to iterate all over the ROI. 038 * @param inclusive 039 * If true then all partially contained (intersected) pixels in the ROI are included. 040 */ 041 public ROIIterator(ROI roi, Rectangle5D region, boolean inclusive) 042 { 043 super(); 044 045 this.roi = roi; 046 // get final bounds 047 if (region != null) 048 bounds = region.createIntersection(roi.getBounds5D()).toInteger(); 049 else 050 bounds = roi.getBounds5D().toInteger(); 051 this.inclusive = inclusive; 052 053 // fix infinite dimensions 054 if (bounds.isInfiniteZ()) 055 { 056 bounds.z = -1; 057 bounds.sizeZ = 1; 058 } 059 if (bounds.isInfiniteT()) 060 { 061 bounds.t = -1; 062 bounds.sizeT = 1; 063 } 064 if (bounds.isInfiniteC()) 065 { 066 bounds.c = -1; 067 bounds.sizeC = 1; 068 } 069 070 // start iterator 071 reset(); 072 } 073 074 /** 075 * Create a new ROI iterator to iterate through each point of the specified ROI. 076 * 077 * @param roi 078 * ROI defining the region to iterate. 079 * @param inclusive 080 * If true then all partially contained (intersected) pixels in the ROI are included. 081 */ 082 public ROIIterator(ROI roi, boolean inclusive) 083 { 084 this(roi, null, inclusive); 085 } 086 087 public int getMinZ() 088 { 089 return bounds.z; 090 } 091 092 public int getMaxZ() 093 { 094 return (bounds.z + bounds.sizeZ) - 1; 095 } 096 097 public int getMinT() 098 { 099 return bounds.t; 100 } 101 102 public int getMaxT() 103 { 104 return (bounds.t + bounds.sizeT) - 1; 105 } 106 107 public int getMinC() 108 { 109 return bounds.c; 110 } 111 112 public int getMaxC() 113 { 114 return (bounds.c + bounds.sizeC) - 1; 115 } 116 117 @Override 118 public void reset() 119 { 120 done = bounds.isEmpty(); 121 122 if (!done) 123 { 124 z = getMinZ(); 125 t = getMinT(); 126 c = getMinC(); 127 128 prepareXY(); 129 nextXYIfNeeded(); 130 } 131 } 132 133 /** 134 * Prepare for XY iteration. 135 */ 136 protected void prepareXY() 137 { 138 maskIterator = new BooleanMask2DIterator(roi.getBooleanMask2D(z, t, c, inclusive)); 139 } 140 141 @Override 142 public void next() 143 { 144 if (done) 145 throw new NoSuchElementException(); 146 147 maskIterator.next(); 148 nextXYIfNeeded(); 149 } 150 151 /** 152 * Advance one image position. 153 */ 154 protected void nextXYIfNeeded() 155 { 156 while (maskIterator.done() && !done) 157 { 158 if (++c > getMaxC()) 159 { 160 c = getMinC(); 161 162 if (++z > getMaxZ()) 163 { 164 z = getMinZ(); 165 166 if (++t > getMaxT()) 167 { 168 done = true; 169 return; 170 } 171 } 172 } 173 174 prepareXY(); 175 } 176 } 177 178 @Override 179 public boolean done() 180 { 181 return done; 182 } 183 184 @Override 185 public Point5D get() 186 { 187 if (done) 188 throw new NoSuchElementException(); 189 190 return new Point5D.Integer(maskIterator.getX(), maskIterator.getY(), z, t, c); 191 } 192 193 @Override 194 public int getX() 195 { 196 if (done) 197 throw new NoSuchElementException(); 198 199 return maskIterator.getX(); 200 } 201 202 @Override 203 public int getY() 204 { 205 if (done) 206 throw new NoSuchElementException(); 207 208 return maskIterator.getY(); 209 } 210 211 @Override 212 public int getC() 213 { 214 if (done) 215 throw new NoSuchElementException(); 216 217 return c; 218 } 219 220 @Override 221 public int getZ() 222 { 223 if (done) 224 throw new NoSuchElementException(); 225 226 return z; 227 } 228 229 @Override 230 public int getT() 231 { 232 if (done) 233 throw new NoSuchElementException(); 234 235 return t; 236 } 237 238}