From d920a150d8d9d045c4ff6ca541003d74c2fecc99 Mon Sep 17 00:00:00 2001 From: bogovicj Date: Tue, 12 Apr 2022 18:37:15 -0400 Subject: [PATCH] add bbox methods specifying number of samples per dimension * fills spacing argument if few than numDims provided --- .../java/net/imglib2/util/RealIntervals.java | 96 +++++++++++++++++-- .../net/imglib2/util/RealIntervalsTests.java | 24 ++++- 2 files changed, 108 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/imglib2/util/RealIntervals.java b/src/main/java/net/imglib2/util/RealIntervals.java index a9dedcf..2aa2311 100644 --- a/src/main/java/net/imglib2/util/RealIntervals.java +++ b/src/main/java/net/imglib2/util/RealIntervals.java @@ -1,7 +1,6 @@ package net.imglib2.util; import java.util.Arrays; -import java.util.stream.IntStream; import net.imglib2.FinalRealInterval; import net.imglib2.RealInterval; @@ -82,13 +81,15 @@ public static RealInterval boundingIntervalCorners( final RealInterval interval, * the real interval * @param transform * the transformation - * @param steps - * step between samples + * @param spacing + * spacing between samples along each dimension * @return the bounding interval */ - public static RealInterval boundingIntervalFaces( final RealInterval interval, final RealTransform xfm, double... steps ) + public static RealInterval boundingIntervalFaces( final RealInterval interval, final RealTransform transform, double... spacing ) { final int nd = interval.numDimensions(); + final double[] itSpacing = fillSpacing( nd, spacing ) ; + final double[] min = new double[ nd ]; final double[] max = new double[ nd ]; Arrays.fill( min, Double.MAX_VALUE ); @@ -102,16 +103,36 @@ public static RealInterval boundingIntervalFaces( final RealInterval interval, f interval.realMax( itvlMax ); itvlMin[ i ] = interval.realMin( i ); itvlMax[ i ] = interval.realMin( i ); - transformedCoordinateBounds( xfm, new LocalizingRealIntervalIterator( itvlMin, itvlMax, steps ), min, max ); + transformedCoordinateBounds( transform, new LocalizingRealIntervalIterator( itvlMin, itvlMax, itSpacing ), min, max ); itvlMin[ i ] = interval.realMax( i ); itvlMax[ i ] = interval.realMax( i ); - transformedCoordinateBounds( xfm, new LocalizingRealIntervalIterator( itvlMin, itvlMax, steps ), min, max ); + transformedCoordinateBounds( transform, new LocalizingRealIntervalIterator( itvlMin, itvlMax, itSpacing ), min, max ); } return new FinalRealInterval( min, max ); } + /** + * Estimate the {@link RealInterval} that bounds the given RealInterval + * after being transformed by a {@link RealTransform}. + *

+ * This implementation estimates the bounding interval by transforming points + * on the faces of the given real interval. + * + * @param interval + * the real interval + * @param transform + * the transformation + * @param numSamples + * number of samples per dimension + * @return the bounding interval + */ + public static RealInterval boundingIntervalFacesSamples( final RealInterval interval, final RealTransform transform, int... numSamples ) + { + return boundingIntervalFaces( interval, transform, stepsFromSamples( interval, numSamples )); + } + /** * Estimate the {@link RealInterval} that bounds the given RealInterval * after being transformed by a {@link RealTransform}. @@ -123,23 +144,47 @@ public static RealInterval boundingIntervalFaces( final RealInterval interval, f * the real interval * @param transform * the transformation - * @param steps - * step between samples + * @param spacing + * spacing between samples along each dimension * @return the bounding interval */ public static RealInterval boundingIntervalVolume( - final RealInterval interval, final RealTransform transform, double... steps ) + final RealInterval interval, final RealTransform transform, double... spacing ) { int nd = interval.numDimensions(); + final double[] itSpacing = fillSpacing( nd, spacing ) ; + double[] min = new double[ nd ]; double[] max = new double[ nd ]; Arrays.fill( min, Long.MAX_VALUE ); Arrays.fill( max, Long.MIN_VALUE ); - final LocalizingRealIntervalIterator it = new LocalizingRealIntervalIterator( interval, steps ); + final LocalizingRealIntervalIterator it = new LocalizingRealIntervalIterator( interval, itSpacing ); transformedCoordinateBounds( transform, it, min, max ); return new FinalRealInterval( min, max ); } + /** + * Estimate the {@link RealInterval} that bounds the given RealInterval + * after being transformed by a {@link RealTransform}. + *

+ * This implementation estimates the bounding interval by transforming + * points in the volume of the given real interval. + * + * @param interval + * the real interval + * @param transform + * the transformation + * @param numSamples + * the number of samples per dimension + * @return the bounding interval + */ + public static RealInterval boundingIntervalVolumeSamples( + final RealInterval interval, final RealTransform transform, int... numSamples ) + { + return boundingIntervalVolume( interval, transform, stepsFromSamples( interval, numSamples )); + + } + /** * Transforms all points produced by the {@link LocalizingRealIntervalIterator} * with the provided {@link RealTransform} and stores the min and max coordinates @@ -176,4 +221,35 @@ protected static void transformedCoordinateBounds( } } + private static double[] fillSpacing( int nd, double... spacing ) + { + final double[] out; + if( spacing.length >= nd ) + out = spacing; + else + { + out = new double[ nd ]; + for( int i = 0; i < nd; i++ ) + if( i < spacing.length ) + out[i] = spacing[ i ]; + else + out[i] = spacing[ spacing.length - 1 ]; + } + return out; + } + + private static double[] stepsFromSamples( final RealInterval interval , int... numSamples ) + { + final double[] out = new double[ interval.numDimensions() ]; + for( int i = 0; i < out.length; i++ ) + { + final double w = interval.realMax( i ) - interval.realMin( i ); + if( i < numSamples.length ) + out[i] = w / numSamples[ i ]; + else + out[i] = w / numSamples[ numSamples.length - 1 ]; + } + return out; + } + } diff --git a/src/test/java/net/imglib2/util/RealIntervalsTests.java b/src/test/java/net/imglib2/util/RealIntervalsTests.java index 7edfcba..0d84992 100644 --- a/src/test/java/net/imglib2/util/RealIntervalsTests.java +++ b/src/test/java/net/imglib2/util/RealIntervalsTests.java @@ -47,7 +47,7 @@ public void testBboxVolumeAffine() final AffineTransform3D xfm = new AffineTransform3D(); xfm.scale(2, 3, 4); - final RealInterval bbox = RealIntervals.boundingIntervalVolume( itvl, xfm, 10, 10, 10 ); + final RealInterval bbox = RealIntervals.boundingIntervalVolume( itvl, xfm, 10 ); assertEquals( "max x ", itvl.realMax(0) * 2, bbox.realMax(0), EPS ); assertEquals( "max y ", itvl.realMax(1) * 3, bbox.realMax(1), EPS ); assertEquals( "max z ", itvl.realMax(2) * 4, bbox.realMax(2), EPS ); @@ -85,13 +85,23 @@ public void testBboxFacesPfield() assertEquals( "min z ", itvl.realMin(2), bbox.realMin(2), EPS ); assertEquals( "max z ", itvl.realMax(2), bbox.realMax(2), EPS ); + + final RealInterval bboxSamples = RealIntervals.boundingIntervalFacesSamples( itvl, xfm, 8, 6, 4 ); + assertEquals( "min x ", itvl.realMin(0), bboxSamples.realMin(0), EPS ); + assertEquals( "max x ", itvl.realMax(0) + 5, bboxSamples.realMax(0), EPS ); + + assertEquals( "min y ", itvl.realMin(1) - 5, bboxSamples.realMin(1), EPS ); + assertEquals( "max y ", itvl.realMax(1), bboxSamples.realMax(1), EPS ); + + assertEquals( "min z ", itvl.realMin(2), bboxSamples.realMin(2), EPS ); + assertEquals( "max z ", itvl.realMax(2), bboxSamples.realMax(2), EPS ); } @Test public void testBboxVolumePfield() { final PositionFieldTransform xfm = pfield(); - final RealInterval bbox = RealIntervals.boundingIntervalVolume( itvl, xfm, 5, 5, 5 ); + final RealInterval bbox = RealIntervals.boundingIntervalVolume( itvl, xfm, 5 ); assertEquals( "min x ", itvl.realMin(0), bbox.realMin(0), EPS ); assertEquals( "max x ", itvl.realMax(0) + 5, bbox.realMax(0), EPS ); @@ -100,6 +110,16 @@ public void testBboxVolumePfield() assertEquals( "min z ", itvl.realMin(2), bbox.realMin(2), EPS ); assertEquals( "max z ", itvl.realMax(2), bbox.realMax(2), EPS ); + + final RealInterval bboxSamples = RealIntervals.boundingIntervalVolumeSamples( itvl, xfm, 8, 6, 4 ); + assertEquals( "min x samples", itvl.realMin(0), bboxSamples.realMin(0), EPS ); + assertEquals( "max x samples", itvl.realMax(0) + 5, bboxSamples.realMax(0), EPS ); + + assertEquals( "min y samples", itvl.realMin(1) - 5, bboxSamples.realMin(1), EPS ); + assertEquals( "max y samples", itvl.realMax(1), bboxSamples.realMax(1), EPS ); + + assertEquals( "min z samples", itvl.realMin(2), bboxSamples.realMin(2), EPS ); + assertEquals( "max z samples", itvl.realMax(2), bboxSamples.realMax(2), EPS ); } private static PositionFieldTransform< DoubleType > pfield()