Skip to content

Commit 16b9649

Browse files
authored
Merge pull request #310 from imagej/realPoint-roi-conversion
Improvements in wrapping RealPointCollections
2 parents 5e703f0 + 0a72924 commit 16b9649

File tree

5 files changed

+138
-68
lines changed

5 files changed

+138
-68
lines changed

src/main/java/net/imagej/legacy/convert/roi/point/RealPointCollectionWrapper.java

+37-21
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@
3232
import ij.gui.PointRoi;
3333

3434
import java.util.Iterator;
35+
import java.util.function.Supplier;
3536

3637
import net.imagej.legacy.convert.roi.MaskPredicateWrapper;
3738
import net.imglib2.RealLocalizable;
3839
import net.imglib2.RealPoint;
40+
import net.imglib2.RealPositionable;
3941
import net.imglib2.roi.geom.real.WritableRealPointCollection;
4042
import net.imglib2.roi.util.RealLocalizableRealPositionable;
4143
import net.imglib2.roi.util.RealLocalizableRealPositionableWrapper;
@@ -47,27 +49,46 @@
4749
*
4850
* @author Alison Walter
4951
*/
50-
public final class RealPointCollectionWrapper extends PointRoi implements
51-
MaskPredicateWrapper<WritableRealPointCollection<RealLocalizableRealPositionable>>
52+
public final class RealPointCollectionWrapper<L extends RealLocalizable & RealPositionable>
53+
extends PointRoi implements
54+
MaskPredicateWrapper<WritableRealPointCollection<L>>
5255
{
5356

54-
private final WritableRealPointCollection<RealLocalizableRealPositionable> rpc;
57+
private final WritableRealPointCollection<L> rpc;
58+
private final Supplier<L> newPointCreator;
5559
private int numPoints;
5660

57-
public RealPointCollectionWrapper(
58-
final WritableRealPointCollection<RealLocalizableRealPositionable> p)
61+
/**
62+
* @deprecated because adding new points through the wrapper is prone to
63+
* {@link ClassCastException}s. Use
64+
* {@link #RealPointCollectionWrapper(WritableRealPointCollection, Supplier)}
65+
* instead.
66+
* @param p the {@link WritableRealPointCollection} that will be wrapped
67+
*/
68+
@Deprecated
69+
@SuppressWarnings("unchecked")
70+
public RealPointCollectionWrapper(final WritableRealPointCollection<L> p) {
71+
this(p, () -> (L) new RealPoint(2));
72+
}
73+
74+
/**
75+
* @param p the {@link WritableRealPointCollection} that will be wrapped
76+
* @param ptCreator defines how new points will be created when added to the
77+
* wrapper.
78+
*/
79+
public RealPointCollectionWrapper(final WritableRealPointCollection<L> p,
80+
final Supplier<L> ptCreator)
5981
{
6082
super(getCoors(p, 0), getCoors(p, 1), countPoints(p));
83+
newPointCreator = ptCreator;
6184
numPoints = getFloatPolygon().npoints;
6285
rpc = p;
6386
}
6487

6588
// -- MaskPredicateWrapper methods --
6689

6790
@Override
68-
public WritableRealPointCollection<RealLocalizableRealPositionable>
69-
getSource()
70-
{
91+
public WritableRealPointCollection<L> getSource() {
7192
return rpc;
7293
}
7394

@@ -76,8 +97,7 @@ public void synchronize() {
7697
// Check if points were added
7798
if (getNCoordinates() > numPoints) {
7899
while (getNCoordinates() != numPoints) {
79-
rpc.addPoint(new RealLocalizableRealPositionableWrapper<>(new RealPoint(
80-
2)));
100+
rpc.addPoint(newPointCreator.get());
81101
numPoints++;
82102
}
83103
}
@@ -90,8 +110,7 @@ public void synchronize() {
90110
}
91111

92112
// Update point locations
93-
final Iterator<RealLocalizableRealPositionable> itr = rpc.points()
94-
.iterator();
113+
final Iterator<L> itr = rpc.points().iterator();
95114
final float[] xCoor = getContainedFloatPoints().xpoints;
96115
final float[] yCoor = getContainedFloatPoints().ypoints;
97116
for (int i = 0; i < numPoints; i++)
@@ -100,24 +119,21 @@ public void synchronize() {
100119

101120
// -- Helper methods --
102121

103-
private static <L extends RealLocalizable> float[] getCoors(
104-
final WritableRealPointCollection<RealLocalizableRealPositionable> rpc,
105-
final int d)
122+
private static <L extends RealLocalizable & RealPositionable> float[]
123+
getCoors(final WritableRealPointCollection<L> rpc, final int d)
106124
{
107125
final FloatArray coor = new FloatArray();
108-
final Iterator<RealLocalizableRealPositionable> itr = rpc.points()
109-
.iterator();
126+
final Iterator<L> itr = rpc.points().iterator();
110127
while (itr.hasNext())
111128
coor.addValue(itr.next().getFloatPosition(d));
112129

113130
return coor.getArray();
114131
}
115132

116-
private static <L extends RealLocalizable> int countPoints(
117-
final WritableRealPointCollection<RealLocalizableRealPositionable> rpc)
133+
private static <L extends RealLocalizable & RealPositionable> int countPoints(
134+
final WritableRealPointCollection<L> rpc)
118135
{
119-
final Iterator<RealLocalizableRealPositionable> itr = rpc.points()
120-
.iterator();
136+
final Iterator<L> itr = rpc.points().iterator();
121137
int count = 0;
122138
while (itr.hasNext()) {
123139
itr.next();

src/main/java/net/imagej/legacy/convert/roi/point/WritableRealPointCollectionToPointRoiConverter.java

+21-10
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,18 @@
3232
import ij.gui.PointRoi;
3333

3434
import net.imagej.legacy.convert.roi.AbstractMaskPredicateToRoiConverter;
35+
import net.imglib2.RealLocalizable;
36+
import net.imglib2.RealPositionable;
3537
import net.imglib2.roi.geom.real.WritableRealPointCollection;
36-
import net.imglib2.roi.util.RealLocalizableRealPositionable;
3738

39+
import org.scijava.convert.ConvertService;
3840
import org.scijava.convert.Converter;
41+
import org.scijava.plugin.Parameter;
3942
import org.scijava.plugin.Plugin;
4043

44+
import java.lang.reflect.Type;
45+
import java.util.function.Supplier;
46+
4147
/**
4248
* Converts a {@link WritableRealPointCollection} to a {@link PointRoi}. This
4349
* conversion may be lossy since PointRoi coordinates are stored as
@@ -46,28 +52,33 @@
4652
* @author Alison Walter
4753
*/
4854
@Plugin(type = Converter.class)
49-
public class WritableRealPointCollectionToPointRoiConverter extends
50-
AbstractMaskPredicateToRoiConverter<WritableRealPointCollection<RealLocalizableRealPositionable>, PointRoi>
55+
public class WritableRealPointCollectionToPointRoiConverter<L extends RealLocalizable & RealPositionable>
56+
extends
57+
AbstractMaskPredicateToRoiConverter<WritableRealPointCollection<L>, PointRoi>
5158
{
5259

60+
@Parameter
61+
public ConvertService convert;
62+
5363
@Override
5464
public Class<PointRoi> getOutputType() {
5565
return PointRoi.class;
5666
}
5767

5868
@Override
5969
@SuppressWarnings({ "unchecked", "rawtypes" })
60-
public Class<WritableRealPointCollection<RealLocalizableRealPositionable>>
61-
getInputType()
62-
{
70+
public Class<WritableRealPointCollection<L>> getInputType() {
6371
return (Class) WritableRealPointCollection.class;
6472
}
6573

6674
@Override
67-
public PointRoi convert(
68-
final WritableRealPointCollection<RealLocalizableRealPositionable> mask)
69-
{
70-
return new RealPointCollectionWrapper(mask);
75+
public PointRoi convert(final WritableRealPointCollection<L> mask) {
76+
float[] srcArray = { 0f, 0f };
77+
Class<?> ptClass = mask.points().iterator().next().getClass();
78+
Converter<float[], L> c = (Converter<float[], L>) convert.getHandler(
79+
srcArray, ptClass);
80+
Supplier<L> ptCreator = () -> (L) c.convert(srcArray, ptClass);
81+
return new RealPointCollectionWrapper<>(mask, ptCreator);
7182
}
7283

7384
@Override

src/test/java/net/imagej/legacy/convert/roi/point/PointRoiConversionTest.java

+17-11
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
public class PointRoiConversionTest {
7272

7373
private PointRoi point;
74-
private WritableRealPointCollection<RealLocalizableRealPositionable> rpc;
74+
private WritableRealPointCollection<RealPoint> rpc;
7575
private WritableRealPointCollection<RealLocalizable> pointRoiWrap;
7676
private PointRoi rpcWrap;
7777
private ConvertService convertService;
@@ -80,16 +80,13 @@ public class PointRoiConversionTest {
8080
public void setup() {
8181
point = new PointRoi(new float[] { 12.125f, 17, 1 }, new float[] { -4, 6.5f,
8282
30 });
83-
final List<RealLocalizableRealPositionable> c = new ArrayList<>();
84-
c.add(new RealLocalizableRealPositionableWrapper<>(new RealPoint(
85-
new double[] { 12.125, -4 })));
86-
c.add(new RealLocalizableRealPositionableWrapper<>(new RealPoint(
87-
new double[] { 17, 6.5 })));
88-
c.add(new RealLocalizableRealPositionableWrapper<>(new RealPoint(
89-
new double[] { 1, 30 })));
83+
final List<RealPoint> c = new ArrayList<>();
84+
c.add(new RealPoint(12.125, -4));
85+
c.add(new RealPoint(17, 6.5 ));
86+
c.add(new RealPoint(1, 30));
9087
rpc = new DefaultWritableRealPointCollection<>(c);
9188
pointRoiWrap = new PointRoiWrapper(point);
92-
rpcWrap = new RealPointCollectionWrapper(rpc);
89+
rpcWrap = new RealPointCollectionWrapper<>(rpc, () -> new RealPoint(2));
9390

9491
final Context context = new Context(ConvertService.class);
9592
convertService = context.service(ConvertService.class);
@@ -199,8 +196,7 @@ public void testWritableRPCToPointRoi() {
199196

200197
final float[] xp = p.getContainedFloatPoints().xpoints;
201198
final float[] yp = p.getContainedFloatPoints().ypoints;
202-
final Iterator<RealLocalizableRealPositionable> points = rpc.points()
203-
.iterator();
199+
final Iterator<RealPoint> points = rpc.points().iterator();
204200
int count = 0;
205201

206202
while (points.hasNext()) {
@@ -215,6 +211,16 @@ public void testWritableRPCToPointRoi() {
215211
assertEquals(rpc.realMin(1), p.getYBase(), 0);
216212
assertEquals(rpc.realMax(0), p.getXBase() + p.getFloatWidth(), 0);
217213
assertEquals(rpc.realMax(1), p.getYBase() + p.getFloatHeight(), 0);
214+
215+
// Add a new point in the wrapper and check for it in the wrapped object
216+
p.addPoint(1.0, 1.0);
217+
assertEquals(rpc.size(), 3);
218+
((RealPointCollectionWrapper<?>) p).synchronize();
219+
assertEquals(rpc.size(), 4);
220+
Iterator<RealPoint> itr = rpc.points().iterator();
221+
for (int i = 0; i < 3; i++)
222+
itr.next();
223+
assertEquals(new RealPoint(1, 1), itr.next());
218224
}
219225

220226
@Test

src/test/java/net/imagej/legacy/convert/roi/point/PointRoiWrapperTest.java

+11-8
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,32 @@
2929

3030
package net.imagej.legacy.convert.roi.point;
3131

32-
import static org.junit.Assert.assertEquals;
33-
import static org.junit.Assert.assertFalse;
34-
import static org.junit.Assert.assertTrue;
35-
3632
import ij.IJ;
3733
import ij.ImagePlus;
3834
import ij.gui.PointRoi;
3935

40-
import java.util.ArrayList;
36+
import java.util.*;
4137
import java.util.Iterator;
42-
import java.util.List;
4338

44-
import net.imglib2.RealLocalizable;
45-
import net.imglib2.RealPoint;
39+
import net.imglib2.*;
40+
import net.imglib2.RandomAccess;
41+
import net.imglib2.img.Img;
42+
import net.imglib2.img.array.ArrayImgs;
43+
import net.imglib2.interpolation.randomaccess.NearestNeighborInterpolatorFactory;
4644
import net.imglib2.roi.geom.real.DefaultWritableRealPointCollection;
4745
import net.imglib2.roi.geom.real.RealPointCollection;
4846
import net.imglib2.roi.geom.real.WritableRealPointCollection;
4947

48+
import net.imglib2.type.numeric.integer.UnsignedByteType;
49+
import net.imglib2.view.Views;
50+
import org.apache.commons.math3.analysis.interpolation.LinearInterpolator;
5051
import org.junit.Before;
5152
import org.junit.Rule;
5253
import org.junit.Test;
5354
import org.junit.rules.ExpectedException;
5455

56+
import static org.junit.Assert.*;
57+
5558
/**
5659
* Tests {@link PointRoiWrapper}
5760
*

src/test/java/net/imagej/legacy/convert/roi/point/RealPointCollectionWrapperTest.java

+52-18
Original file line numberDiff line numberDiff line change
@@ -29,49 +29,51 @@
2929

3030
package net.imagej.legacy.convert.roi.point;
3131

32-
import static org.junit.Assert.assertEquals;
33-
import static org.junit.Assert.assertFalse;
34-
import static org.junit.Assert.assertTrue;
35-
3632
import ij.IJ;
3733
import ij.ImagePlus;
3834

3935
import java.util.ArrayList;
36+
import java.util.Collections;
4037
import java.util.Iterator;
4138
import java.util.List;
4239

4340
import net.imglib2.RealLocalizable;
4441
import net.imglib2.RealPoint;
42+
import net.imglib2.RealRandomAccess;
43+
import net.imglib2.RealRandomAccessible;
44+
import net.imglib2.img.array.ArrayImgs;
45+
import net.imglib2.interpolation.randomaccess.NearestNeighborInterpolatorFactory;
4546
import net.imglib2.roi.geom.real.DefaultWritableRealPointCollection;
4647
import net.imglib2.roi.geom.real.WritableRealPointCollection;
47-
import net.imglib2.roi.util.RealLocalizableRealPositionable;
48-
import net.imglib2.roi.util.RealLocalizableRealPositionableWrapper;
4948

49+
import net.imglib2.type.numeric.integer.UnsignedByteType;
50+
import net.imglib2.view.Views;
5051
import org.junit.Before;
5152
import org.junit.Test;
5253

54+
import static org.junit.Assert.*;
55+
import static org.junit.Assert.assertArrayEquals;
56+
5357
/**
5458
* Tests {@link RealPointCollectionWrapper}
5559
*
5660
* @author Alison Walter
61+
* @author Gabriel Selzer
5762
*/
5863
public class RealPointCollectionWrapperTest {
5964

60-
private WritableRealPointCollection<RealLocalizableRealPositionable> rpc;
61-
private RealPointCollectionWrapper wrap;
65+
private WritableRealPointCollection<RealPoint> rpc;
66+
private RealPointCollectionWrapper<RealPoint> wrap;
6267

6368
@Before
6469
public void setup() {
65-
final List<RealLocalizableRealPositionable> pts = new ArrayList<>(3);
66-
pts.add(new RealLocalizableRealPositionableWrapper<>(new RealPoint(
67-
new double[] { 12, 3 })));
68-
pts.add(new RealLocalizableRealPositionableWrapper<>(new RealPoint(
69-
new double[] { 0.25, 6.5 })));
70-
pts.add(new RealLocalizableRealPositionableWrapper<>(new RealPoint(
71-
new double[] { -107, 33 })));
70+
final List<RealPoint> pts = new ArrayList<>(3);
71+
pts.add(new RealPoint(12, 3));
72+
pts.add(new RealPoint(0.25, 6.5));
73+
pts.add(new RealPoint(-107, 33));
7274

7375
rpc = new DefaultWritableRealPointCollection<>(pts);
74-
wrap = new RealPointCollectionWrapper(rpc);
76+
wrap = new RealPointCollectionWrapper<>(rpc, () -> new RealPoint(2));
7577

7678
// NB: can't remove points without associated image
7779
final ImagePlus i = IJ.createImage("Ramp", "8-bit ramp", 128, 128, 1);
@@ -138,6 +140,39 @@ public void testRemovePoint() {
138140
assertTrue(pointsEqual());
139141
}
140142

143+
/**
144+
* Ensures that {@link WritableRealPointCollection}s can wrap
145+
* {@link RealRandomAccess}es (i.e. something that is not a {@link RealPoint})
146+
*/
147+
@Test
148+
public void testRPCOfRandomAccesses() {
149+
RealRandomAccessible<UnsignedByteType> testImg = Views.interpolate(ArrayImgs
150+
.unsignedBytes(10, 10), new NearestNeighborInterpolatorFactory<>());
151+
RealRandomAccess<UnsignedByteType> ra1 = testImg.realRandomAccess();
152+
ra1.setPosition(new int[] { 1, 1 });
153+
WritableRealPointCollection<RealRandomAccess<UnsignedByteType>> rpc =
154+
new DefaultWritableRealPointCollection<>(Collections.singletonList(ra1));
155+
156+
RealPointCollectionWrapper<RealRandomAccess<UnsignedByteType>> wrapped =
157+
new RealPointCollectionWrapper<>(rpc, testImg::realRandomAccess);
158+
159+
// add a new point
160+
wrapped.addPoint(2.0, 3.0);
161+
wrapped.synchronize();
162+
163+
// assert there are now two RRAs
164+
assertEquals(2, rpc.size());
165+
Iterator<RealRandomAccess<UnsignedByteType>> iw = rpc.points().iterator();
166+
RealRandomAccess<UnsignedByteType> ra = iw.next();
167+
assertArrayEquals(new double[] { 1.0, 1.0 }, ra.positionAsDoubleArray(),
168+
1e-6);
169+
ra = iw.next();
170+
assertArrayEquals(new double[] { 2.0, 3.0 }, ra.positionAsDoubleArray(),
171+
1e-6);
172+
assertFalse(iw.hasNext());
173+
174+
}
175+
141176
// -- Helper methods --
142177

143178
private boolean pointsEqual() {
@@ -146,8 +181,7 @@ private boolean pointsEqual() {
146181
final float[] yp = wrap.getFloatPolygon().ypoints;
147182

148183
int count = 0;
149-
final Iterator<RealLocalizableRealPositionable> itr = rpc.points()
150-
.iterator();
184+
final Iterator<RealPoint> itr = rpc.points().iterator();
151185
while (itr.hasNext()) {
152186
final RealLocalizable pt = itr.next();
153187
boolean match = false;

0 commit comments

Comments
 (0)