Skip to content

Commit b3479d9

Browse files
committed
Use List rather than array, accept super type in extractor
1 parent 35aa042 commit b3479d9

6 files changed

Lines changed: 92 additions & 100 deletions

File tree

src/main/java/com/goebl/simplify/AbstractSimplify.java

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@
1212
*/
1313
abstract class AbstractSimplify<T> {
1414

15-
private T[] sampleArray;
16-
17-
protected AbstractSimplify(T[] sampleArray) {
18-
this.sampleArray = sampleArray;
15+
protected AbstractSimplify() {
1916
}
2017

2118
/**
@@ -27,12 +24,15 @@ protected AbstractSimplify(T[] sampleArray) {
2724
* applying Douglas-Peucker (should be a bit faster)
2825
* @return simplified list of points
2926
*/
30-
public T[] simplify(T[] points,
27+
public List<T> simplify(List<T> points,
3128
double tolerance,
3229
boolean highestQuality) {
3330

34-
if (points == null || points.length <= 2) {
35-
return points;
31+
if (points == null) {
32+
throw new IllegalArgumentException();
33+
}
34+
if (points.size() <= 2) {
35+
return new ArrayList<>(points);
3636
}
3737

3838
double sqTolerance = tolerance * tolerance;
@@ -46,15 +46,15 @@ public T[] simplify(T[] points,
4646
return points;
4747
}
4848

49-
T[] simplifyRadialDistance(T[] points, double sqTolerance) {
49+
List<T> simplifyRadialDistance(List<T> points, double sqTolerance) {
5050
T point = null;
51-
T prevPoint = points[0];
51+
T prevPoint = points.get(0);
5252

53-
List<T> newPoints = new ArrayList<T>();
53+
List<T> newPoints = new ArrayList<>();
5454
newPoints.add(prevPoint);
5555

56-
for (int i = 1; i < points.length; ++i) {
57-
point = points[i];
56+
for (int i = 1; i < points.size(); ++i) {
57+
point = points.get(i);
5858

5959
if (getSquareDistance(point, prevPoint) > sqTolerance) {
6060
newPoints.add(point);
@@ -66,7 +66,7 @@ T[] simplifyRadialDistance(T[] points, double sqTolerance) {
6666
newPoints.add(point);
6767
}
6868

69-
return newPoints.toArray(sampleArray);
69+
return newPoints;
7070
}
7171

7272
private static class Range {
@@ -79,14 +79,14 @@ private Range(int first, int last) {
7979
int last;
8080
}
8181

82-
T[] simplifyDouglasPeucker(T[] points, double sqTolerance) {
82+
List<T> simplifyDouglasPeucker(List<T> points, double sqTolerance) {
8383

84-
BitSet bitSet = new BitSet(points.length);
84+
BitSet bitSet = new BitSet(points.size());
8585
bitSet.set(0);
86-
bitSet.set(points.length - 1);
86+
bitSet.set(points.size() - 1);
8787

88-
List<Range> stack = new ArrayList<Range>();
89-
stack.add(new Range(0, points.length - 1));
88+
List<Range> stack = new ArrayList<>();
89+
stack.add(new Range(0, points.size() - 1));
9090

9191
while (!stack.isEmpty()) {
9292
Range range = stack.remove(stack.size() - 1);
@@ -96,7 +96,7 @@ T[] simplifyDouglasPeucker(T[] points, double sqTolerance) {
9696

9797
// find index of point with maximum square distance from first and last point
9898
for (int i = range.first + 1; i < range.last; ++i) {
99-
double sqDist = getSquareSegmentDistance(points[i], points[range.first], points[range.last]);
99+
double sqDist = getSquareSegmentDistance(points.get(i), points.get(range.first), points.get(range.last));
100100

101101
if (sqDist > maxSqDist) {
102102
index = i;
@@ -112,12 +112,12 @@ T[] simplifyDouglasPeucker(T[] points, double sqTolerance) {
112112
}
113113
}
114114

115-
List<T> newPoints = new ArrayList<T>(bitSet.cardinality());
115+
List<T> newPoints = new ArrayList<>(bitSet.cardinality());
116116
for (int index = bitSet.nextSetBit(0); index >= 0; index = bitSet.nextSetBit(index + 1)) {
117-
newPoints.add(points[index]);
117+
newPoints.add(points.get(index));
118118
}
119119

120-
return newPoints.toArray(sampleArray);
120+
return newPoints;
121121
}
122122

123123

src/main/java/com/goebl/simplify/Simplify.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,19 @@
88
*/
99
public class Simplify<T> extends AbstractSimplify<T> {
1010

11-
private final PointExtractor<T> pointExtractor;
11+
private final PointExtractor<? super T> pointExtractor;
1212

1313
/**
1414
* Simple constructor for 2D-Simplifier.
1515
* <br>
1616
* With this simple constructor your array elements must implement {@link Point}.<br>
1717
* If you have coordinate classes which cannot be changed to implement <code>Point</code>, use
18-
* {@link #Simplify(Object[], PointExtractor)} constructor!
18+
* {@link #Simplify(PointExtractor)} constructor!
1919
*
20-
* @param sampleArray pass just an empty array (<code>new MyPoint[0]</code>) - necessary for type consistency.
2120
*/
22-
public Simplify(T[] sampleArray) {
23-
super(sampleArray);
24-
this.pointExtractor = new PointExtractor<T>() {
21+
public Simplify() {
22+
super();
23+
this.pointExtractor = new PointExtractor<>() {
2524
@Override
2625
public double getX(T point) {
2726
return ((Point) point).getX();
@@ -40,11 +39,10 @@ public double getY(T point) {
4039
* With this constructor your array elements do not have to implement a special interface like {@link Point}.<br>
4140
* Implement a {@link PointExtractor} to give <code>Simplify</code> access to your coordinates.
4241
*
43-
* @param sampleArray pass just an empty array (<code>new MyPoint[0]</code>) - necessary for type consistency.
4442
* @param pointExtractor your implementation to extract X and Y coordinates from you array elements.
4543
*/
46-
public Simplify(T[] sampleArray, PointExtractor<T> pointExtractor) {
47-
super(sampleArray);
44+
public Simplify(PointExtractor<? super T> pointExtractor) {
45+
super();
4846
this.pointExtractor = pointExtractor;
4947
}
5048

src/main/java/com/goebl/simplify/Simplify3D.java

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,18 @@
88
*/
99
public class Simplify3D<T> extends AbstractSimplify<T> {
1010

11-
private final Point3DExtractor<T> pointExtractor;
11+
private final Point3DExtractor<? super T> pointExtractor;
1212

1313
/**
1414
* Simple constructor for 3D-Simplifier.
1515
* <br>
1616
* With this simple constructor your array elements must implement {@link Point3D}.<br>
1717
* If you have coordinate classes which cannot be changed to implement <code>Point3D</code>, use
18-
* {@link #Simplify3D(Object[], Point3DExtractor)} constructor!
19-
*
20-
* @param sampleArray pass just an empty array (<code>new MyPoint[0]</code>) - necessary for type consistency.
18+
* {@link #Simplify3D(Point3DExtractor)} constructor!
2119
*/
22-
public Simplify3D(T[] sampleArray) {
23-
super(sampleArray);
24-
this.pointExtractor = new Point3DExtractor<T>() {
20+
public Simplify3D() {
21+
super();
22+
this.pointExtractor = new Point3DExtractor<>() {
2523
@Override
2624
public double getX(T point) {
2725
return ((Point) point).getX();
@@ -45,11 +43,10 @@ public double getZ(T point) {
4543
* With this constructor your array elements do not have to implement a special interface like {@link Point3D}.<br>
4644
* Implement a {@link Point3DExtractor} to give <code>Simplify3D</code> access to your coordinates.
4745
*
48-
* @param sampleArray pass just an empty array (<code>new MyPoint[0]</code>) - necessary for type consistency.
4946
* @param pointExtractor your implementation to extract X, Y and Z coordinates from you array elements.
5047
*/
51-
public Simplify3D(T[] sampleArray, Point3DExtractor<T> pointExtractor) {
52-
super(sampleArray);
48+
public Simplify3D(Point3DExtractor<? super T> pointExtractor) {
49+
super();
5350
this.pointExtractor = pointExtractor;
5451
}
5552

src/test/java/com/goebl/simplify/GpsLocationTest.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* Test class for {@link Simplify} in context of typical Gps-Tracks.
1212
* <br>
1313
* This is more of a demonstration than a test.
14-
* See http://stackoverflow.com/q/34010298/2176962
14+
* See <a href="http://stackoverflow.com/q/34010298/2176962">http://stackoverflow.com/q/34010298/2176962</a>
1515
*
1616
* @author goebl
1717
* @since 01.12.15
@@ -36,9 +36,9 @@ public double getLng() {
3636
}
3737
}
3838

39-
private static LatLng[] coords;
39+
private static List<LatLng> coords;
4040

41-
private static PointExtractor<LatLng> latLngPointExtractor = new PointExtractor<LatLng>() {
41+
private static final PointExtractor<LatLng> latLngPointExtractor = new PointExtractor<>() {
4242
@Override
4343
public double getX(LatLng point) {
4444
return point.getLat() * 1000000;
@@ -53,25 +53,25 @@ public double getY(LatLng point) {
5353
@BeforeClass
5454
public static void readPoints() throws Exception {
5555
Point[] allPoints = SimplifyTest.readPoints("gps-track.txt");
56-
List<LatLng> coordsList = new ArrayList<LatLng>(allPoints.length);
56+
List<LatLng> coordsList = new ArrayList<>(allPoints.length);
5757

5858
for (Point point:allPoints) {
5959
coordsList.add(new LatLng(point.getX(), point.getY()));
6060
}
61-
coords = coordsList.toArray(new LatLng[coordsList.size()]);
61+
coords = coordsList;
6262
}
6363

6464
@Test
65-
public void testSimplifyGpsTrack() throws Exception {
66-
Simplify<LatLng> simplify = new Simplify<LatLng>(new LatLng[0], latLngPointExtractor);
65+
public void testSimplifyGpsTrack() {
66+
Simplify<LatLng> simplify = new Simplify<>(latLngPointExtractor);
6767

68-
LatLng[] simplified = simplify.simplify(coords, 20f, false);
69-
System.out.println("coords:" + coords.length + " simplified:" + simplified.length);
70-
Assert.assertTrue("should be simplified to less than 33%", simplified.length < (coords.length / 3));
68+
List<LatLng> simplified = simplify.simplify(coords, 20f, false);
69+
System.out.println("coords:" + coords.size() + " simplified:" + simplified.size());
70+
Assert.assertTrue("should be simplified to less than 33%", simplified.size() < (coords.size() / 3));
7171

7272
simplified = simplify.simplify(coords, 50f, true);
73-
System.out.println("coords:" + coords.length + " simplified:" + simplified.length);
74-
Assert.assertTrue("should be simplified to less than 20%", simplified.length < (coords.length * 0.2));
73+
System.out.println("coords:" + coords.size() + " simplified:" + simplified.size());
74+
Assert.assertTrue("should be simplified to less than 20%", simplified.size() < (coords.size() * 0.2));
7575
}
7676

7777
}

src/test/java/com/goebl/simplify/Simplify3DTest.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
import org.junit.Assert;
44
import org.junit.Test;
55

6+
import java.util.ArrayList;
7+
import java.util.Arrays;
8+
import java.util.List;
9+
610
/**
711
* Test class for {@link com.goebl.simplify.Simplify}.
812
*
@@ -17,7 +21,7 @@ public class Simplify3DTest {
1721

1822
@Test
1923
public void testCustomPoint3DExtractor() {
20-
Point3DExtractor<float[]> pointExtractor = new Point3DExtractor<float[]>() {
24+
Point3DExtractor<float[]> pointExtractor = new Point3DExtractor<>() {
2125
@Override
2226
public double getX(float[] point) {
2327
return point[0];
@@ -34,29 +38,29 @@ public double getZ(float[] point) {
3438
}
3539
};
3640

37-
Simplify3D<float[]> simplify = new Simplify3D<float[]>(new float[0][0], pointExtractor);
41+
Simplify3D<float[]> simplify = new Simplify3D<>(pointExtractor);
3842

39-
float[][] simplified = simplify.simplify(POINTS_3D, 5.0f, false);
40-
Assert.assertEquals("array should be simplified", 2, simplified.length);
43+
List<float[]> simplified = simplify.simplify(Arrays.stream(POINTS_3D).toList(), 5.0f, false);
44+
Assert.assertEquals("array should be simplified", 2, simplified.size());
4145

42-
simplified = simplify.simplify(POINTS_3D, 5.0f, true);
43-
Assert.assertEquals("array should be simplified", 2, simplified.length);
46+
simplified = simplify.simplify(Arrays.stream(POINTS_3D).toList(), 5.0f, true);
47+
Assert.assertEquals("array should be simplified", 2, simplified.size());
4448
}
4549

4650
@Test
4751
public void testDefaultPointExtractor() {
48-
Point3D[] points = new MyPoint[POINTS_3D.length];
49-
for (int i = 0; i < POINTS_3D.length; ++i) {
50-
points[i] = new MyPoint(POINTS_3D[i][0], POINTS_3D[i][1], POINTS_3D[i][2]);
52+
List<Point3D> points = new ArrayList<>();
53+
for (float[] floats : POINTS_3D) {
54+
points.add(new MyPoint(floats[0], floats[1], floats[2]));
5155
}
5256

53-
Simplify3D<Point3D> simplify3D = new Simplify3D<Point3D>(new MyPoint[0]);
57+
Simplify3D<Point3D> simplify3D = new Simplify3D<>();
5458

55-
Point3D[] simplified = simplify3D.simplify(points, 5.0d, false);
56-
Assert.assertEquals("array should be simplified", 2, simplified.length);
59+
List<Point3D> simplified = simplify3D.simplify(points, 5.0d, false);
60+
Assert.assertEquals("array should be simplified", 2, simplified.size());
5761

5862
simplified = simplify3D.simplify(points, 5.0d, true);
59-
Assert.assertEquals("array should be simplified", 2, simplified.length);
63+
Assert.assertEquals("array should be simplified", 2, simplified.size());
6064
}
6165

6266
private static class MyPoint implements Point3D {
@@ -99,9 +103,7 @@ public boolean equals(Object o) {
99103

100104
if (Double.compare(myPoint.x, x) != 0) return false;
101105
if (Double.compare(myPoint.y, y) != 0) return false;
102-
if (Double.compare(myPoint.z, z) != 0) return false;
103-
104-
return true;
106+
return Double.compare(myPoint.z, z) == 0;
105107
}
106108

107109
}

0 commit comments

Comments
 (0)