/**
* Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onebusaway.geospatial.grid;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.onebusaway.geospatial.model.CoordinateBounds;
import org.onebusaway.geospatial.model.CoordinatePoint;
import org.onebusaway.geospatial.model.EncodedPolygonBean;
import org.onebusaway.geospatial.services.PolylineEncoder;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class GridFactoryTest {
private static final double DELTA = 0.001;
private static Comparator<CoordinatePoint> POINTS_COMPARATOR = new CoordinatePointComparator();
private static Comparator<CoordinateBounds> BOUNDS_COMPARATOR = new CoordinateBoundsComparator();
private static Comparator<EncodedPolygonBean> POLYGON_COMPARATOR = new EncodedPolygonBeanComparator();
@Test
public void test01() {
GridFactory factory = new GridFactory(0.1,0.1);
CoordinateBounds bounds = new CoordinateBounds(5.05, 4.05, 5.15, 4.15);
factory.addBounds(bounds);
List<CoordinateBounds> grid = factory.getGrid();
assertEquals(4, grid.size());
Collections.sort(grid, BOUNDS_COMPARATOR);
checkBounds(grid.get(0), new CoordinateBounds(5.0, 4.0, 5.1, 4.1), DELTA);
checkBounds(grid.get(1), new CoordinateBounds(5.0, 4.1, 5.1, 4.2), DELTA);
checkBounds(grid.get(2), new CoordinateBounds(5.1, 4.0, 5.2, 4.1), DELTA);
checkBounds(grid.get(3), new CoordinateBounds(5.1, 4.1, 5.2, 4.2), DELTA);
List<EncodedPolygonBean> boundary = factory.getBoundary();
assertEquals(1, boundary.size());
EncodedPolygonBean polygon = boundary.get(0);
assertTrue(polygon.getInnerRings().isEmpty());
List<CoordinatePoint> points = PolylineEncoder.decode(polygon.getOuterRing());
points = shiftPoints(points);
assertEquals(8, points.size());
assertEqualsPoints(new CoordinatePoint(5.0, 4.0), points.get(0), DELTA);
assertEqualsPoints(new CoordinatePoint(5.1, 4.0), points.get(1), DELTA);
assertEqualsPoints(new CoordinatePoint(5.2, 4.0), points.get(2), DELTA);
assertEqualsPoints(new CoordinatePoint(5.2, 4.1), points.get(3), DELTA);
assertEqualsPoints(new CoordinatePoint(5.2, 4.2), points.get(4), DELTA);
assertEqualsPoints(new CoordinatePoint(5.1, 4.2), points.get(5), DELTA);
assertEqualsPoints(new CoordinatePoint(5.0, 4.2), points.get(6), DELTA);
assertEqualsPoints(new CoordinatePoint(5.0, 4.1), points.get(7), DELTA);
factory.addBounds(new CoordinateBounds(5.15, 4.05, 5.26, 4.19));
grid = factory.getGrid();
assertEquals(6, grid.size());
Collections.sort(grid, BOUNDS_COMPARATOR);
checkBounds(grid.get(0), new CoordinateBounds(5.0, 4.0, 5.1, 4.1), DELTA);
checkBounds(grid.get(1), new CoordinateBounds(5.0, 4.1, 5.1, 4.2), DELTA);
checkBounds(grid.get(2), new CoordinateBounds(5.1, 4.0, 5.2, 4.1), DELTA);
checkBounds(grid.get(3), new CoordinateBounds(5.1, 4.1, 5.2, 4.2), DELTA);
checkBounds(grid.get(4), new CoordinateBounds(5.2, 4.0, 5.3, 4.1), DELTA);
checkBounds(grid.get(5), new CoordinateBounds(5.2, 4.1, 5.3, 4.2), DELTA);
boundary = factory.getBoundary();
assertEquals(1, boundary.size());
polygon = boundary.get(0);
assertTrue(polygon.getInnerRings().isEmpty());
points = PolylineEncoder.decode(polygon.getOuterRing());
points = shiftPoints(points);
assertEquals(10, points.size());
assertEqualsPoints(new CoordinatePoint(5.0, 4.0), points.get(0), DELTA);
assertEqualsPoints(new CoordinatePoint(5.1, 4.0), points.get(1), DELTA);
assertEqualsPoints(new CoordinatePoint(5.2, 4.0), points.get(2), DELTA);
assertEqualsPoints(new CoordinatePoint(5.3, 4.0), points.get(3), DELTA);
assertEqualsPoints(new CoordinatePoint(5.3, 4.1), points.get(4), DELTA);
assertEqualsPoints(new CoordinatePoint(5.3, 4.2), points.get(5), DELTA);
assertEqualsPoints(new CoordinatePoint(5.2, 4.2), points.get(6), DELTA);
assertEqualsPoints(new CoordinatePoint(5.1, 4.2), points.get(7), DELTA);
assertEqualsPoints(new CoordinatePoint(5.0, 4.2), points.get(8), DELTA);
assertEqualsPoints(new CoordinatePoint(5.0, 4.1), points.get(9), DELTA);
}
@Test
public void test02() {
GridFactory factory = new GridFactory(1,1);
CoordinateBounds bounds = new CoordinateBounds(1.5, 2.5, 2.5, 3.5);
factory.addBounds(bounds);
List<CoordinateBounds> grid = factory.getGrid();
assertEquals(4, grid.size());
Collections.sort(grid, BOUNDS_COMPARATOR);
checkBounds(grid.get(0), new CoordinateBounds(1.0, 2.0, 2.0, 3.0), DELTA);
checkBounds(grid.get(1), new CoordinateBounds(1.0, 3.0, 2.0, 4.0), DELTA);
checkBounds(grid.get(2), new CoordinateBounds(2.0, 2.0, 3.0, 3.0), DELTA);
checkBounds(grid.get(3), new CoordinateBounds(2.0, 3.0, 3.0, 4.0), DELTA);
List<EncodedPolygonBean> boundary = factory.getBoundary();
assertEquals(1, boundary.size());
EncodedPolygonBean polygon = boundary.get(0);
assertTrue(polygon.getInnerRings().isEmpty());
List<CoordinatePoint> points = PolylineEncoder.decode(polygon.getOuterRing());
points = shiftPoints(points);
assertEquals(8, points.size());
assertEqualsPoints(new CoordinatePoint(1.0, 2.0), points.get(0), DELTA);
assertEqualsPoints(new CoordinatePoint(2.0, 2.0), points.get(1), DELTA);
assertEqualsPoints(new CoordinatePoint(3.0, 2.0), points.get(2), DELTA);
assertEqualsPoints(new CoordinatePoint(3.0, 3.0), points.get(3), DELTA);
assertEqualsPoints(new CoordinatePoint(3.0, 4.0), points.get(4), DELTA);
assertEqualsPoints(new CoordinatePoint(2.0, 4.0), points.get(5), DELTA);
assertEqualsPoints(new CoordinatePoint(1.0, 4.0), points.get(6), DELTA);
assertEqualsPoints(new CoordinatePoint(1.0, 3.0), points.get(7), DELTA);
factory.addBounds(new CoordinateBounds(5.5, 4.5, 5.6, 4.6));
grid = factory.getGrid();
assertEquals(5, grid.size());
Collections.sort(grid, BOUNDS_COMPARATOR);
checkBounds(grid.get(0), new CoordinateBounds(1.0, 2.0, 2.0, 3.0), DELTA);
checkBounds(grid.get(1), new CoordinateBounds(1.0, 3.0, 2.0, 4.0), DELTA);
checkBounds(grid.get(2), new CoordinateBounds(2.0, 2.0, 3.0, 3.0), DELTA);
checkBounds(grid.get(3), new CoordinateBounds(2.0, 3.0, 3.0, 4.0), DELTA);
checkBounds(grid.get(4), new CoordinateBounds(5.0, 4.0, 6.0, 5.0), DELTA);
boundary = factory.getBoundary();
assertEquals(2, boundary.size());
Collections.sort(boundary, POLYGON_COMPARATOR);
polygon = boundary.get(0);
assertTrue(polygon.getInnerRings().isEmpty());
points = PolylineEncoder.decode(polygon.getOuterRing());
points = shiftPoints(points);
assertEquals(8, points.size());
assertEqualsPoints(new CoordinatePoint(1.0, 2.0), points.get(0), DELTA);
assertEqualsPoints(new CoordinatePoint(2.0, 2.0), points.get(1), DELTA);
assertEqualsPoints(new CoordinatePoint(3.0, 2.0), points.get(2), DELTA);
assertEqualsPoints(new CoordinatePoint(3.0, 3.0), points.get(3), DELTA);
assertEqualsPoints(new CoordinatePoint(3.0, 4.0), points.get(4), DELTA);
assertEqualsPoints(new CoordinatePoint(2.0, 4.0), points.get(5), DELTA);
assertEqualsPoints(new CoordinatePoint(1.0, 4.0), points.get(6), DELTA);
assertEqualsPoints(new CoordinatePoint(1.0, 3.0), points.get(7), DELTA);
polygon = boundary.get(1);
assertTrue(polygon.getInnerRings().isEmpty());
points = PolylineEncoder.decode(polygon.getOuterRing());
points = shiftPoints(points);
assertEquals(4, points.size());
assertEqualsPoints(new CoordinatePoint(5.0, 4.0), points.get(0), DELTA);
assertEqualsPoints(new CoordinatePoint(6.0, 4.0), points.get(1), DELTA);
assertEqualsPoints(new CoordinatePoint(6.0, 5.0), points.get(2), DELTA);
assertEqualsPoints(new CoordinatePoint(5.0, 5.0), points.get(3), DELTA);
}
/****
* Private Methods
****/
private void checkBounds(CoordinateBounds a, CoordinateBounds b, double delta) {
assertEquals(a.getMinLat(), b.getMinLat(), delta);
assertEquals(a.getMaxLat(), b.getMaxLat(), delta);
assertEquals(a.getMinLon(), b.getMinLon(), delta);
assertEquals(a.getMaxLon(), b.getMaxLon(), delta);
}
private static void assertEqualsPoints(CoordinatePoint p1,
CoordinatePoint p2, double delta) {
assertEquals(p1.getLat(), p2.getLat(), delta);
assertEquals(p1.getLon(), p2.getLon(), delta);
}
private static List<CoordinatePoint> shiftPoints(List<CoordinatePoint> points) {
if (points.size() < 2)
return points;
int minIndex = 0;
CoordinatePoint minPoint = null;
for (int index = 0; index < points.size(); index++) {
CoordinatePoint p = points.get(index);
if (minPoint == null || POINTS_COMPARATOR.compare(p, minPoint) < 0) {
minIndex = index;
minPoint = p;
}
}
List<CoordinatePoint> shifted = new ArrayList<CoordinatePoint>();
for (int i = minIndex; i < points.size(); i++)
shifted.add(points.get(i));
for (int i = 0; i < minIndex; i++)
shifted.add(points.get(i));
return shifted;
}
private static class CoordinatePointComparator implements
Comparator<CoordinatePoint> {
public int compare(CoordinatePoint p1, CoordinatePoint p2) {
int rc = Double.compare(p1.getLat(), p2.getLat());
if (rc == 0)
rc = Double.compare(p1.getLon(), p2.getLon());
return rc;
}
}
private static class CoordinateBoundsComparator implements
Comparator<CoordinateBounds> {
public int compare(CoordinateBounds o1, CoordinateBounds o2) {
int rc = Double.compare(o1.getMinLat(), o2.getMinLat());
if (rc == 0)
rc = Double.compare(o1.getMaxLat(), o2.getMaxLat());
if (rc == 0)
rc = Double.compare(o1.getMinLon(), o2.getMinLon());
if (rc == 0)
rc = Double.compare(o1.getMaxLon(), o2.getMaxLon());
return rc;
}
}
private static class EncodedPolygonBeanComparator implements
Comparator<EncodedPolygonBean> {
public int compare(EncodedPolygonBean o1, EncodedPolygonBean o2) {
return o1.getOuterRing().getPoints().compareTo(
o2.getOuterRing().getPoints());
}
}
}