/** * ***************************************************************************** * Copyright 2013 Sebastian Müller * * 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 de.fub.agg2graph.pt; import com.infomatiq.jsi.Point; import com.infomatiq.jsi.Rectangle; import com.infomatiq.jsi.SpatialIndex; import com.infomatiq.jsi.rtree.RTree; import com.viniciusfortuna.transit.gtfs.GtfsReader; import com.viniciusfortuna.transit.gtfs.GtfsSpec; import com.viniciusfortuna.transit.gtfs.Stop; import de.fub.agg2graph.structs.GPSCalc; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Properties; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; /** * @author Sebastian Müller * * This class creates an R-Tree from GTFS stops.txt files and provides the * possibility to search for nearest Stops. * */ public class StopTree { private final static Level LOGLEVEL = Level.INFO; private final static String LOGLAYOUT = "%-5p [%t]: %m%n"; private final static String RELPATHTOZIP = "/com/viniciusfortuna/transit/gtfs/BVG.zip"; private final static float MAXDISTANCE = 5.5F; private SpatialIndex si = new RTree(); private PTIntProcedure proc = new PTIntProcedure(); private HashMap<Integer, Stop> stopsMeta = new HashMap<Integer, Stop>(); public void init() { init(LOGLEVEL, RELPATHTOZIP); } public void init(Level logLevel) { init(logLevel, RELPATHTOZIP); } public void init(String pathToZip) { init(LOGLEVEL, pathToZip); } /** * @param logLevel The Log4J LogLevel * @param pathToZip The relative Path to a GTFS Zip File */ public void init(Level logLevel, String pathToZip) { final Logger rootLogger = Logger.getRootLogger(); rootLogger.setLevel(logLevel); rootLogger.addAppender(new ConsoleAppender(new PatternLayout( LOGLAYOUT))); Properties p = new Properties(); p.setProperty("MinNodeEntries", "10"); p.setProperty("MaxNodeEntries", "50"); si.init(p); try { InputStream is = GtfsReader.class.getResourceAsStream(pathToZip); GtfsSpec spec = GtfsReader.readGtfsFile(is); List<Stop> list = spec.getStops(); Iterator<Stop> it = list.iterator(); int id = 1; while (it.hasNext()) { Stop stop = it.next(); Rectangle rec = new Rectangle(); rec.set((float) stop.longitude, (float) stop.latitude, (float) stop.longitude, (float) stop.latitude); stopsMeta.put(id, stop); si.add(rec, id); id++; } } catch (NumberFormatException e) { rootLogger.error(e.getMessage()); } catch (MalformedURLException e) { rootLogger.error(e.getMessage()); } catch (IOException e) { rootLogger.error(e.getMessage()); } } /** * @param p The point to which the nearest stop shall be found * @return The distance to the nearest stop. */ public Double getNearestDistance(Point p) { Stop stop = getNearestStop(p); return stop == null ? MAXDISTANCE : GPSCalc.getDistance(p.y, p.x, stop.latitude, stop.longitude); } public Stop getNearestStop(Point p) { return getNearestStop(p, MAXDISTANCE); } /** * @param p The Point to which the nearest Stop should be found. * @param maxDistance The maximum search distance to limit search. * @return The nearest Stop. */ public Stop getNearestStop(Point p, float maxDistance) { Integer id = getNearest(p, maxDistance); Stop stop = stopsMeta.get(id); return stop; } public Integer getNearest(Point p) { return getNearest(p, MAXDISTANCE); } public Integer getNearest(Point p, float maxDistance) { si.nearest(p, proc, maxDistance); return proc.getId(); } }