/** * License: GPL * <p> * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public * License 2 as published by the Free Software Foundation. * <p> * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * <p> * You should have received a copy of the GNU General Public License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package net.imglib2.util; import net.imglib2.FinalInterval; import net.imglib2.Interval; import net.imglib2.Localizable; import net.imglib2.RandomAccess; import net.imglib2.RandomAccessible; /** * A {@link RandomAccessible} that tracks the bounding box in which its * {@link RandomAccess} has moved. If the {@link RandomAccess} did not move, the * bounding box covers the complete range from (2<sup>-63</sup>)<sup>n</sup> to * (2<sup>63</sup>)<sup>n</sup> but with min pointing at max and max pointing at * min. I.e. the initialization of the {@link RandomAccess} at 0<sup>n</sup> is * not considered part of the access box. * * This {@link RandomAccessible} has a singleton {@link RandomAccess} (itself) * such that updates of the access box do not have to be synchronized. If using * in multithreaded contexts, make many instances of the * {@link RandomAccessible}, and merge the access boxes later * * @author Stephan Saalfeld <[email protected]> */ public class AccessBoxRandomAccessible<T> implements RandomAccessible<T>, RandomAccess<T> { final protected RandomAccessible<T> source; protected RandomAccess<T> sourceAccess; final protected long[] min; final protected long[] max; public AccessBoxRandomAccessible(final RandomAccessible<T> source) { this.source = source; min = new long[source.numDimensions()]; max = new long[source.numDimensions()]; sourceAccess = source.randomAccess(); } protected void initAccessBox() { for (int i = 0; i < min.length; ++i) { min[i] = Long.MAX_VALUE; max[i] = Long.MIN_VALUE; } } protected void updateAccessBox(final int d) { final long x = sourceAccess.getLongPosition(d); if (x < min[d]) min[d] = x; if (x > max[d]) max[d] = x; } protected void updateAccessBox() { for (int d = 0; d < min.length; ++d) updateAccessBox(d); } public long[] getMin() { return min; } public long[] getMax() { return max; } public Interval createAccessInterval() { return new FinalInterval(min, max); } @Override public int numDimensions() { return source.numDimensions(); } @Override public RandomAccess<T> randomAccess() { sourceAccess = source.randomAccess(); initAccessBox(); return this; } @Override public RandomAccess<T> randomAccess(final Interval interval) { sourceAccess = source.randomAccess(interval); initAccessBox(); return this; } @Override public int getIntPosition(final int d) { return sourceAccess.getIntPosition(d); } @Override public long getLongPosition(final int d) { return sourceAccess.getLongPosition(d); } @Override public void localize(final int[] position) { sourceAccess.localize(position); } @Override public void localize(final long[] position) { sourceAccess.localize(position); } @Override public double getDoublePosition(final int d) { return sourceAccess.getDoublePosition(d); } @Override public float getFloatPosition(final int d) { return sourceAccess.getFloatPosition(d); } @Override public void localize(final float[] position) { sourceAccess.localize(position); } @Override public void localize(final double[] position) { sourceAccess.localize(position); } @Override public void bck(final int d) { sourceAccess.bck(d); final long x = sourceAccess.getLongPosition(d); if (x < min[d]) min[d] = x; } @Override public void fwd(final int d) { sourceAccess.fwd(d); final long x = sourceAccess.getLongPosition(d); if (x > max[d]) max[d] = x; } @Override public void move(final Localizable distance) { sourceAccess.move(distance); updateAccessBox(); } @Override public void move(final int[] distance) { sourceAccess.move(distance); updateAccessBox(); } @Override public void move(final long[] distance) { sourceAccess.move(distance); updateAccessBox(); } @Override public void move(final int distance, final int d) { sourceAccess.move(distance, d); updateAccessBox(d); } @Override public void move(final long distance, final int d) { sourceAccess.move(distance, d); updateAccessBox(d); } @Override public void setPosition(final Localizable position) { sourceAccess.setPosition(position); updateAccessBox(); } @Override public void setPosition(final int[] position) { sourceAccess.setPosition(position); updateAccessBox(); } @Override public void setPosition(final long[] position) { sourceAccess.setPosition(position); updateAccessBox(); } @Override public void setPosition(final int position, final int d) { sourceAccess.setPosition(position, d); updateAccessBox(d); } @Override public void setPosition(final long position, final int d) { sourceAccess.setPosition(position, d); updateAccessBox(d); } @Override public AccessBoxRandomAccessible<T> copy() { return this; } @Override public T get() { return sourceAccess.get(); } @Override public AccessBoxRandomAccessible<T> copyRandomAccess() { return copy(); } }