I am trying to implement a reduction algorithm from https://github.com/hgoebl/simplify-java
I looked at his test code and tried to find what, in my opinion, is the correct logic.
I take a list of objects Location, converting them to Point, starting the reduction algorithm, and then converting the given points back to the list of objects Location.
The problem is here:
float[][] simplified = simplify.simplify(points2D, 10000.0f, true);
It always comes out with size 2. It is clear that I am doing something wrong, but I'm not sure what. Can you determine what is wrong with my implementation?
Approach No. 1 with an error
public static ArrayList<Location> reducePath(List<Location> allLocations, double tolerance)
{
float[][] points2D = new float[allLocations.size()][2];
int i = 0;
for (Location loc:allLocations)
{
points2D[i][0] = (float)loc.getLatitude();
points2D[i][1] = (float)loc.getLongitude();
i++;
}
PointExtractor<float[]> pointExtractor = new PointExtractor<float[]>()
{
@Override
public double getX(float[] point)
{
return point[0];
}
@Override
public double getY(float[] point)
{
return point[1];
}
};
Timber.tag("Thin").d("2D array size " + points2D.length);
Simplify<float[]> simplify = new Simplify<float[]>(new float[0][0], pointExtractor);
float[][] simplified = simplify.simplify(points2D, 10000.0f, true);
Timber.tag("Thin").d("Simplified with size " + simplified.length);
ArrayList<Location> reducedPoints = new ArrayList<>();
for(float[] point:simplified)
{
Location loc = new Location("");
loc.setLatitude(point[0]);
loc.setLongitude(point[1]);
reducedPoints.add(loc);
}
return reducedPoints;
}
Approach No. 2 also does not work.
I also tried this approach:
public static ArrayList<Location> reducePath(List<Location> allLocations, double tolerance)
{
float[][] points2D = new float[allLocations.size()][2];
Simplify<MyPoint> simplify = new Simplify<MyPoint>(new MyPoint[0]);
MyPoint[] allpoints = new MyPoint[allLocations.size()];
int i = 0;
for (Location loc:allLocations)
{
points2D[i][0] = (float)loc.getLatitude();
points2D[i][1] = (float)loc.getLongitude();
MyPoint p = new MyPoint(loc.getLatitude(), (float)loc.getLongitude());
allpoints[i] = p;
i++;
}
Timber.tag("Thin").d("All points array size " + allpoints.length);
MyPoint[] simplified = simplify.simplify(allpoints, 1.0, false);
Timber.tag("Thin").d("Simplified with size " + simplified.length);
ArrayList<Location> reducedPoints = new ArrayList<>();
for(MyPoint point:simplified)
{
Location loc = new Location("");
loc.setLatitude(point.getX());
loc.setLongitude(point.getY());
reducedPoints.add(loc);
}
return reducedPoints;
}
private static class MyPoint implements Point
{
double x;
double y;
private MyPoint(double x, double y)
{
this.x = x;
this.y = y;
}
@Override
public double getX()
{
return x;
}
@Override
public double getY()
{
return y;
}
@Override
public String toString()
{
return "{" + "x=" + x + ", y=" + y + '}';
}
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyPoint myPoint = (MyPoint) o;
if (Double.compare(myPoint.x, x) != 0) return false;
if (Double.compare(myPoint.y, y) != 0) return false;
return true;
}
}
Both of these hyperlinks reduce my points to the first and last locations.
.
, , . :
private static int DELTA_SCALAR = 1000000;
private static float EPSILON_TOLERANCE = 400.0f;
public static ArrayList<Location> reducePath(ArrayList<Location> allLocations)
{
PointExtractor<Location> pointExtractor = new PointExtractor<Location>()
{
@Override
public double getX(Location location)
{
return location.getLatitude() * DELTA_SCALAR;
}
@Override
public double getY(Location location)
{
return location.getLongitude() * DELTA_SCALAR;
}
};
Simplify<Location> simplify = new Simplify<Location>(new Location[0], pointExtractor);
Location[] allLocationsArray = new Location[allLocations.size()];
allLocations.toArray(allLocationsArray);
Location[] simplifiedArray = simplify.simplify(allLocationsArray, EPSILON_TOLERANCE, true);
return new ArrayList<Location>(Arrays.asList(simplifiedArray));
}