/** * 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 org.onebusaway.geospatial.model.CoordinateBounds; import org.onebusaway.geospatial.model.CoordinatePoint; import org.onebusaway.geospatial.model.EncodedPolygonBean; import org.onebusaway.geospatial.model.EncodedPolylineBean; import org.onebusaway.geospatial.services.PolylineEncoder; import java.util.ArrayList; import java.util.List; public class GridFactory { private double _gridLatStep; private double _gridLonStep; protected Grid<Object> _grid = new MapGrid<Object>(); public GridFactory(double gridLatStep, double gridLonStep) { _gridLatStep = gridLatStep; _gridLonStep = gridLonStep; } public List<EncodedPolygonBean> getBoundary() { BoundaryFactory factory = new BoundaryFactory(); List<Boundary> boundaries = factory.getBoundaries(_grid); return getBoundariesAsBeans(boundaries); } public void addBounds(CoordinateBounds bounds) { int latIndexMin = (int) Math.floor(bounds.getMinLat() / _gridLatStep); int latIndexMax = (int) Math.ceil(bounds.getMaxLat() / _gridLatStep); int lonIndexMin = (int) Math.floor(bounds.getMinLon() / _gridLonStep); int lonIndexMax = (int) Math.ceil(bounds.getMaxLon() / _gridLonStep); for (int latIndex = latIndexMin; latIndex < latIndexMax; latIndex++) { for (int lonIndex = lonIndexMin; lonIndex < lonIndexMax; lonIndex++) { GridIndex index = new GridIndex(lonIndex, latIndex); addCell(index, this); } } } public List<CoordinateBounds> getGrid() { List<CoordinateBounds> results = new ArrayList<CoordinateBounds>(); for (Grid.Entry<Object> entry : _grid.getEntries()) { GridIndex index = entry.getIndex(); CoordinateBounds bounds = getIndexAsBounds(index); results.add(bounds); } return results; } protected CoordinateBounds getIndexAsBounds(GridIndex index) { double minLat = index.getY() * _gridLatStep; double minLon = index.getX() * _gridLonStep; double maxLat = minLat + _gridLatStep; double maxLon = minLon + _gridLonStep; return new CoordinateBounds(minLat, minLon, maxLat, maxLon); } protected void getIndexAndDirectionAsPoint(GridIndex index, EDirection direction, DoublePoint point) { double minLat = index.getY() * _gridLatStep; double minLon = index.getX() * _gridLonStep; double maxLat = minLat + _gridLatStep; double maxLon = minLon + _gridLonStep; switch (direction) { case UP: point.lat = maxLat; point.lon = minLon; break; case RIGHT: point.lat = maxLat; point.lon = maxLon; break; case DOWN: point.lat = minLat; point.lon = maxLon; break; case LEFT: point.lat = minLat; point.lon = minLon; break; default: throw new IllegalStateException(); } } protected void addCell(GridIndex index, Object value) { _grid.set(index, value); } protected List<EncodedPolygonBean> getBoundariesAsBeans( List<Boundary> boundaries) { List<EncodedPolygonBean> beans = new ArrayList<EncodedPolygonBean>( boundaries.size()); for (Boundary boundary : boundaries) { EncodedPolygonBean bean = getBoundaryAsPolygonBean(boundary); beans.add(bean); } return beans; } protected EncodedPolygonBean getBoundaryAsPolygonBean(Boundary boundary) { EncodedPolygonBean bean = new EncodedPolygonBean(); EncodedPolylineBean outerRing = getPathAsEncodedPath(boundary.getOuterBoundary()); bean.setOuterRing(outerRing); for (BoundaryPath path : boundary.getInnerBoundaries()) { EncodedPolylineBean innerRing = getPathAsEncodedPath(path); bean.addInnerRing(innerRing); } return bean; } protected EncodedPolylineBean getPathAsEncodedPath(BoundaryPath path) { DoublePoint p = new DoublePoint(); List<CoordinatePoint> points = new ArrayList<CoordinatePoint>(path.size()); for (int i = 0; i < path.size(); i++) { getIndexAndDirectionAsPoint(path.getIndex(i), path.getDirection(i), p); CoordinatePoint cp = new CoordinatePoint(p.lat, p.lon); points.add(cp); } // Re-add the first point to close the loop // I don't think this is actually right // points.add(points.get(0)); return PolylineEncoder.createEncodings(points); } protected static class DoublePoint { double lat; double lon; } }