public static ArrayList<GeoPoint> reduceWithTolerance(ArrayList<GeoPoint> shape, double tolerance) {
        int n = shape.size();
        // if a shape has 2 or less points it cannot be reduced
        if (tolerance <= 0 || n < 3) {
            return shape;
        }

        boolean[] marked = new boolean[n]; //vertex indexes to keep will be marked as "true"
        for (int i = 1; i < n - 1; i++)
            marked[i] = false;
        // automatically add the first and last point to the returned shape
        marked[0] = marked[n - 1] = true;

        // the first and last points in the original shape are
        // used as the entry point to the algorithm.
        douglasPeuckerReduction(
                shape,             // original shape
                marked,          // reduced shape
                tolerance,         // tolerance
                0,                  // index of first point
                n - 1  // index of last point
        );

        // all done, return the reduced shape
        ArrayList<GeoPoint> newShape = new ArrayList<GeoPoint>(n); // the new shape to return
        for (int i = 0; i < n; i++) {
            if (marked[i])
                newShape.add(shape.get(i));
        }
        return newShape;
    }
@Test
    public void testReducer() {
        ArrayList<GeoPoint> pts = new ArrayList<>();
        pts.add(new GeoPoint(45, -74.0));
        pts.add(new GeoPoint(45.0009, -74.0009));   //about 1km
        pts.add(new GeoPoint(45.0018, -74.0018));   //about 1km

        ArrayList<GeoPoint> geoPoints = PointReducer.reduceWithTolerance(pts, 0.5 / 312);   //about 50km latitude span
        Assert.assertTrue(!geoPoints.isEmpty());
        Assert.assertTrue(geoPoints.size() + "", geoPoints.size() == 2);
    }