// This software is released into the Public Domain. See copying.txt for details. package org.openstreetmap.osmosis.areafilter.v0_6; import org.openstreetmap.osmosis.core.filter.common.IdTrackerType; import org.openstreetmap.osmosis.core.pipeline.common.TaskConfiguration; import org.openstreetmap.osmosis.core.pipeline.common.TaskManager; import org.openstreetmap.osmosis.core.pipeline.v0_6.SinkSourceManager; /** * The task manager factory for a bounding box filter. * * @author Brett Henderson */ public class BoundingBoxFilterFactory extends AreaFilterTaskManagerFactory { private static final String ARG_LEFT = "left"; private static final String ARG_RIGHT = "right"; private static final String ARG_TOP = "top"; private static final String ARG_BOTTOM = "bottom"; private static final String ARG_X1 = "x1"; private static final String ARG_Y1 = "y1"; private static final String ARG_X2 = "x2"; private static final String ARG_Y2 = "y2"; private static final String ARG_ZOOM = "zoom"; private static final String ARG_CLIP_INCOMPLETE_ENTITIES = "clipIncompleteEntities"; private static final String ARG_COMPLETE_WAYS = "completeWays"; private static final String ARG_COMPLETE_RELATIONS = "completeRelations"; private static final String ARG_CASCADING_RELATIONS = "cascadingRelations"; private static final double DEFAULT_LEFT = -180; private static final double DEFAULT_RIGHT = 180; private static final double DEFAULT_TOP = 90; private static final double DEFAULT_BOTTOM = -90; private static final int DEFAULT_ZOOM = 12; private static final boolean DEFAULT_CLIP_INCOMPLETE_ENTITIES = false; private static final boolean DEFAULT_COMPLETE_WAYS = false; private static final boolean DEFAULT_COMPLETE_RELATIONS = false; private static final boolean DEFAULT_CASCADING_RELATIONS = false; private double xToLon(int zoom, int x) { double unit = 360 / Math.pow(2, zoom); return -180 + x * unit; } private double projectF(double lat) { // Project latitude to mercator return Math.log(Math.tan(lat) + 1 / Math.cos(lat)); } private double projectMercToLat(double y) { return Math.toDegrees(Math.atan(Math.sinh(y))); } private double yToLat(int zoom, int y) { // Convert zoom/y to mercator // Get maximum range of mercator coordinates double limitY = projectF(Math.atan(Math.sinh(Math.PI))); double limitY2 = projectF((Math.atan(Math.sinh(-Math.PI)))); double rangeY = limitY - limitY2; double unit = 1 / Math.pow(2, zoom); double relY = limitY - rangeY * y * unit; // Mercator to latitude return projectMercToLat(relY); } /** * {@inheritDoc} */ @Override protected TaskManager createTaskManagerImpl(TaskConfiguration taskConfig) { IdTrackerType idTrackerType; double left; double right; double top; double bottom; boolean clipIncompleteEntities; boolean completeWays; boolean completeRelations; boolean cascadingRelations; int zoom; // Get the task arguments. idTrackerType = getIdTrackerType(taskConfig); left = getDoubleArgument(taskConfig, ARG_LEFT, DEFAULT_LEFT); right = getDoubleArgument(taskConfig, ARG_RIGHT, DEFAULT_RIGHT); top = getDoubleArgument(taskConfig, ARG_TOP, DEFAULT_TOP); bottom = getDoubleArgument(taskConfig, ARG_BOTTOM, DEFAULT_BOTTOM); clipIncompleteEntities = getBooleanArgument( taskConfig, ARG_CLIP_INCOMPLETE_ENTITIES, DEFAULT_CLIP_INCOMPLETE_ENTITIES); completeWays = getBooleanArgument(taskConfig, ARG_COMPLETE_WAYS, DEFAULT_COMPLETE_WAYS); completeRelations = getBooleanArgument(taskConfig, ARG_COMPLETE_RELATIONS, DEFAULT_COMPLETE_RELATIONS); cascadingRelations = getBooleanArgument(taskConfig, ARG_CASCADING_RELATIONS, DEFAULT_CASCADING_RELATIONS); zoom = getIntegerArgument(taskConfig, ARG_ZOOM, DEFAULT_ZOOM); if (doesArgumentExist(taskConfig, ARG_X1)) { int x1 = getIntegerArgument(taskConfig, ARG_X1); left = xToLon(zoom, x1); right = xToLon(zoom, getIntegerArgument(taskConfig, ARG_X2, x1) + 1); } if (doesArgumentExist(taskConfig, ARG_Y1)) { int y1 = getIntegerArgument(taskConfig, ARG_Y1); top = yToLat(zoom, y1); bottom = yToLat(zoom, getIntegerArgument(taskConfig, ARG_Y2, y1) + 1); } return new SinkSourceManager( taskConfig.getId(), new BoundingBoxFilter(idTrackerType, left, right, top, bottom, clipIncompleteEntities, completeWays, completeRelations, cascadingRelations), taskConfig.getPipeArgs() ); } }