/* ------------------------------------------------------------------------- OpenTripPlanner GWT Client Copyright (C) 2015 Mecatran - info@mecatran.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ------------------------------------------------------------------------- */ package com.mecatran.otp.gwt.client.proxies; import java.util.ArrayList; import java.util.List; import java.util.Map; import com.mecatran.otp.gwt.client.i18n.I18nUtils; import com.mecatran.otp.gwt.client.model.LocationBean; import com.mecatran.otp.gwt.client.model.POIBean; import com.mecatran.otp.gwt.client.model.Wgs84BoundsBean; import com.mecatran.otp.gwt.client.model.Wgs84LatLonBean; import com.mecatran.otp.gwt.client.proxies.POISource.POIListener; import com.mecatran.otp.gwt.client.utils.HaversineDistance; /** * This class encapsulate a POISource to make a GeocoderProxy. * */ public class POIGeocoder implements GeocoderProxy, POIListener { private Map<String, POIBean> pois; private Wgs84BoundsBean bounds; private boolean useBounds; public POIGeocoder(POISource poiSource, boolean useBounds) { this.useBounds = useBounds; poiSource.addListener(this); } @Override public void poiUpdate(POISource source, Map<String, POIBean> pois) { this.pois = pois; } @Override public void configure(Wgs84BoundsBean bounds, String mainCountryName) { this.bounds = bounds; } @Override public void geocode(String address, GeocoderListener listener) { List<LocationBean> locations = new ArrayList<LocationBean>(); String upperAddress = address.toUpperCase(); if (address.length() >= 3 && pois != null) { for (POIBean poi : pois.values()) { if (poi.getName().toUpperCase().contains(upperAddress) && (useBounds && bounds.contains(poi.getLocation()) || !useBounds)) { LocationBean location = new LocationBean(); location.setLocation(poi.getLocation()); location.setAddress(translatePoi(poi)); locations.add(location); if (locations.size() > 10) break; } } } listener.onGeocodingDone(locations); } @Override public void reverseGeocode(Wgs84LatLonBean location, ReverseGeocoderListener listener) { POIBean bestPoi = null; double bestDist = 10000; if (pois != null) { for (POIBean poi : pois.values()) { double dist = HaversineDistance.computeHaversineDistance( location.getLat(), location.getLon(), poi.getLocation() .getLat(), poi.getLocation().getLon()); if (dist < bestDist) { bestDist = dist; bestPoi = poi; } } } if (bestDist < 500) { LocationBean location2 = new LocationBean(); location2.setAddress(translatePoi(bestPoi)); location2.setLocation(bestPoi.getLocation()); // bestDist = 0 m -> factor = 10000/50 = 200 // bestDist = 100 m -> factor = 10000/150 = 66 // bestDist = 500 m -> factor = 10000/550 = 18 listener.onReverseGeocodingDone(location2, (int) (10000 / (bestDist + 50))); } else { listener.onReverseGeocodingDone(null, 0); } } private String translatePoi(POIBean poi) { String msg; switch (poi.getType()) { case TRANSPORT_BIKE_RENTAL_STATION: msg = I18nUtils.tr("geocode.bike-rental", poi.getName()); break; case TRANSPORT_STATION: msg = I18nUtils.tr("geocode.transport", poi.getName()); break; default: msg = I18nUtils.tr("geocode.poi", poi.getName()); break; } return msg; } }